/******************************************************************************
* Copyright (c) 2012 - 2020 Xilinx, Inc.  All rights reserved.
* SPDX-License-Identifier: MIT
 ******************************************************************************/

/*****************************************************************************/
/**
 *
 * @file xilisf.c
 *
 * This file contains the library functions to initialize, control and read the
 * device information of the Serial Flash devices. Refer xilisf.h for detailed
 * description.
 *
 * <pre>
 *
 * MODIFICATION HISTORY:
 *
 * Ver   Who      Date     Changes
 * ----- -------  -------- -----------------------------------------------
 * 1.00a ksu/sdm  03/03/08 First release
 * 1.00a sdm      07/02/08 Changed the initialization so that the SPI
 *			  Master works in Spi Mode 3 as the In-System Flash
 *			  works only in Spi Mode 3
 * 2.00a ktn	11/27/09 Updated to use HAL processor APIs/definitions
 * 2.01a sdm	01/04/10 Added Support for Winbond W25QXX/W25XX devices
 *			  The parameter PagesPerBlock in the struct
 *			  IntelStmDeviceGeometry has been renamed to
 *			  PagesPerSector.
 * 2.03a sdm      04/17/10 Updated to support Winbond memory W25Q128.
 * 2.04a sdm      08/17/10 Updated to support Numonyx (N25QXX) and Spansion
 *			  flash memories
 * 3.00a srt	 06/20/12 Updated to support interfaces SPI PS and QSPI PS.
 *             New API:
 *               XIsf_RegisterInterface()
 *               XIsf_SetSpiConfiguration()
 *               XIsf_SetTransferMode()
 *             Changed API:
 *               XIsf_Initialize()
 *               XIsf_Transfer()
 *             Added support to SST flash.
 * 3.01a srt	 02/06/13 Updated for changes made in QSPIPS driver
 *			  (CR 698107).
 * 5.0   sb	 08/05/14 Updated for support for > 128 MB flash for PSQSPI
 *             Interface. Added Library Handler API which will
 *             register to driver interrupts, based upon the
 *             interface selected.
 *             New API:
 *               SpaMicWinFlashInitialize()
 *               GetRealAddr()
 *               SendBankSelect()
 *               XIsf_SetStatusHandler()
 *               void XIsf_IfaceHandler()
 *             Changed API:
 *               - XIsf_Initialize()
 *               Added Call back to lib interrupt handler
 *               after XIsf_Transfer Call
 *               - XIsf_Transfer()
 *               - XIsf_GetStatus()
 *               - XIsf_GetStatusReg2()
 *               - XIsf_GetDeviceInfo()
 *               - XIsf_WriteEnable()
 *               - XIsf_Ioctl()
 * 5.1   sb	 12/23/14 Added check for flash interface for Winbond, Spansion
 *			  and Micron flash family for PSQSPI.
 * 5.2   asa  05/12/15 Added APIs to support 4 byte addressing for Micron flash.
 *                     2 APIs were added, one to enter into 4 byte mode and
 *                     the other to exit from the same.
 * 5.3   sk   08/07/17 Added QSPIPSU flash interface support for ZynqMP.
 * 5.4   nsk  09/14/15 Updated IntelStmDevices list to support Micron N25Q256A
 *                     (CR 881478).
 * 5.5   sk   01/14/16 Updated IntelStmDevices list to add support for S25FL512S
 *                     and S25FL256S.
 *       sk   03/02/16 Added support for MT25QU01G.
 * 5.9   ms   08/03/17 Added tags and modified comment lines style for doxygen.
 * 5.10  tjs  11/30/17 Added description of S25FL-L series flash
 *                     parts in IntelStmDevices array. CR# 987566
 * 5.10	tjs  03/01/18 Added MT25Q512 3V and 1.8V flash part support. CR# 995477
 * 5.11	tjs  03/16/18 Added support for ISSI flash part.
 * 5.12	tjs  05/02/18 Added support for IS25LP064A and IS25WP064A.
 * 5.12  tjs  06/05/18 Added support for Macronix 1G flash parts. CR#978447
 * 5.12 tjs	 06/18/18 Removed checkpatch and gcc warnings.
 * 5.12 tjs  06/18/18 Added support for MT25QL01G and MT25QL02G 3V
 *					  flash.CR#1004264
 * 5.12 tjs  06/18/18 Added support for low density ISSI
 *		      flash parts. PR#9237
 * 5.13 nsk  01/22/19 Make variable declaration to XQspiPsu_Msg as global
 *                    CR#1015808.
 * 5.13 akm  01/30/19 Fixed multiple definition error in C++ project
 *                         CR#1019773
 *      sk   02/11/19 Added support for OSPI flash interface.
 * 5.13	akm  02/26/19 Added support for ISSI serial NOR Flash Devices.
 * 	         	   PR# 11442
 *      sk   02/28/19 Added support for SST26WF016B flash.
 * 5.14	akm  08/01/19 Initialized Status variable to XST_FAILURE.
 *
 *
 * </pre>
 *
 ******************************************************************************/

/***************************** Include Files *********************************/

#include "include/xilisf.h"

/************************** Constant Definitions *****************************/

#define SIXTEENMB	0x1000000	/**< Sixteen MB */

/************************** Variable Definition *****************************/

u32 XIsf_StatusEventInfo;
unsigned int XIsf_ByteCountInfo;

/**************************** Type Definitions *******************************/

#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
/**
 * The following structure specifies the geometry of the Atmel Serial Flash.
 */
struct AtmelDeviceGeometry {
	u8 DeviceCode;          /**< Device code */
	u16 BytesPerPageDefaultMode;    /**< Bytes per Page in Default mode */
	u16 BytesPerPagePowerOf2Mode;   /**< Bytes per Page in PowerOf2 mode */
	u8 PagesPerBlock;       /**< Number of Pages per Block */
	u8 BlocksPerSector;     /**< Number of Blocks per Sector */
	u8 NumOfSectors;        /**< Number of Sectors in the device */
};
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */

#if (((XPAR_XISF_FLASH_FAMILY == INTEL) || (XPAR_XISF_FLASH_FAMILY == STM) \
	|| (XPAR_XISF_FLASH_FAMILY == SST) ||       \
	(XPAR_XISF_FLASH_FAMILY == WINBOND) ||      \
	(XPAR_XISF_FLASH_FAMILY == SPANSION)) &&    \
	((!defined(XPAR_XISF_INTERFACE_PSQSPI)) &&  \
	(!defined(XPAR_XISF_INTERFACE_QSPIPSU)) && \
	(!defined(XPAR_XISF_INTERFACE_OSPIPSV))))
/**
 * The following structure specifies the geometry of the Intel/STM Serial Flash.
 */
struct IntelStmDeviceGeometry {
	u8 ManufacturerID;		/**< Manufacturer code */
	u16 DeviceCode;			/**< Device code */
	u16 BytesPerPage;		/**< Bytes per Page */
	u16 PagesPerSector;		/**< Number of Pages per Sector */
	u16 NumOfSectors;		/**< Number of Sectors in the device */
};
#endif
/**
 *  (((XPAR_XISF_FLASH_FAMILY == INTEL) ||
 *  (XPAR_XISF_FLASH_FAMILY == STM) || \
 *  (XPAR_XISF_FLASH_FAMILY == SST) || \
 *  (XPAR_XISF_FLASH_FAMILY == WINBOND) || \
 *  (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \
 *  ((!defined(XPAR_XISF_INTERFACE_PSQSPI)) &&  \
 *  (!defined(XPAR_XISF_INTERFACE_QSPIPSU)) && \
 *	(!defined(XPAR_XISF_INTERFACE_OSPIPSV))))
 */

#if (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \
	(XPAR_XISF_FLASH_FAMILY == SPANSION)) && \
	(defined(XPAR_XISF_INTERFACE_PSQSPI)	|| \
	defined(XPAR_XISF_INTERFACE_QSPIPSU) || \
	defined(XPAR_XISF_INTERFACE_OSPIPSV)))
/**
 * The following structure specifies the geometry of the Spansion/Micron
 * Serial Flash.
 */
struct SpaMicWinDeviceGeometry {
	u32 SectSize;			/**< Individual sector size or
					  * combined sector size in
					  * case of parallel config
					  */
	u32 NumSect;			/**< Total no. of sectors in one/two
					  * flash devices
					  */
	u32 PageSize;			/**< Individual page size or
					  * combined page size in
					  * case of parallel
					  * config
					  */
	u32 NumPage;			/**< Total no. of pages in one/two flash
					  * devices
					  */
	u32 FlashDeviceSize;		/**< This is the size of one
					  * flash device NOT the
					  * combination of both devices,
					  * if present
					  */
	u8 ManufacturerID;	/**< Manufacturer ID - used to identify make */
	u8 DeviceIDMemSize;		/**< Byte of device ID
					  * indicating the memory
					  * size
					  */
	u32 SectMask;	/**< Mask to get sector start address */
	u8 NumDie;		/**< No. of die forming a single flash */
};

#endif
/**
 * (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \
 * (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \
 * (defined(XPAR_XISF_INTERFACE_PSQSPI)  || \
 * defined(XPAR_XISF_INTERFACE_QSPIPSU) || \
 * defined(XPAR_XISF_INTERFACE_OSPIPSV)))
 */


/***************** Macros (Inline Functions) Definitions *********************/

/************************** Function Prototypes ******************************/

#ifdef XPAR_XISF_INTERFACE_PSQSPI
int SendBankSelect(XIsf *InstancePtr, u32 BankSel);
#endif

#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
static int AtmelFlashInitialize(XIsf *InstancePtr, u8 *ReadBuf);
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */

#if (((XPAR_XISF_FLASH_FAMILY == INTEL) || \
	(XPAR_XISF_FLASH_FAMILY == STM) || \
	(XPAR_XISF_FLASH_FAMILY == SST) || \
	(XPAR_XISF_FLASH_FAMILY == WINBOND) || \
	(XPAR_XISF_FLASH_FAMILY == SPANSION)) && \
	((!defined(XPAR_XISF_INTERFACE_PSQSPI)) && \
	(!defined(XPAR_XISF_INTERFACE_QSPIPSU)) && \
	(!defined(XPAR_XISF_INTERFACE_OSPIPSV))))
static int IntelStmFlashInitialize(XIsf *InstancePtr, u8 *ReadBuf);
#endif
#ifdef XPAR_XISF_INTERFACE_QSPIPSU
	static XQspiPsu_Msg FlashMsg[2];
#elif defined(XPAR_XISF_INTERFACE_OSPIPSV)
	static XOspiPsv_Msg FlashMsg;
#endif
/**
 * (((XPAR_XISF_FLASH_FAMILY == INTEL) || \
 * (XPAR_XISF_FLASH_FAMILY == STM) || \
 * (XPAR_XISF_FLASH_FAMILY == SST) || \
 * (XPAR_XISF_FLASH_FAMILY == WINBOND) || \
 * (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \
 * ((!defined(XPAR_XISF_INTERFACE_PSQSPI)) && \
 * (!defined(XPAR_XISF_INTERFACE_QSPIPSU)) && \
 * (!defined(XPAR_XISF_INTERFACE_OSPIPSV))))
 */

#if (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \
	(XPAR_XISF_FLASH_FAMILY == SPANSION)) && \
	(defined(XPAR_XISF_INTERFACE_PSQSPI) || \
	defined(XPAR_XISF_INTERFACE_QSPIPSU) || \
	defined(XPAR_XISF_INTERFACE_OSPIPSV)))
static int SpaMicWinFlashInitialize(XIsf *InstancePtr, u8 *BufferPtr);

#endif
/**
 * (((XPAR_XISF_FLASH_FAMILY == WINBOND) ||	\
 * (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \
 * (defined(XPAR_XISF_INTERFACE_PSQSPI)	|| \
 * defined(XPAR_XISF_INTERFACE_QSPIPSU) || \
 * defined(XPAR_XISF_INTERFACE_OSPIPSV)))
 */

/************************** Variable Definitions *****************************/

#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
static const struct AtmelDeviceGeometry AtmelDevices[] = {

	{XISF_ATMEL_DEV_AT45DB011D, XISF_BYTES264_PER_PAGE,
	XISF_BYTES256_PER_PAGE, XISF_PAGES8_PER_BLOCK,
	XISF_BLOCKS16_PER_SECTOR, XISF_NUM_OF_SECTORS4},

	{XISF_ATMEL_DEV_AT45DB021D, XISF_BYTES264_PER_PAGE,
	XISF_BYTES256_PER_PAGE, XISF_PAGES8_PER_BLOCK,
	XISF_BLOCKS16_PER_SECTOR, XISF_NUM_OF_SECTORS8},

	{XISF_ATMEL_DEV_AT45DB041D, XISF_BYTES264_PER_PAGE,
	XISF_BYTES256_PER_PAGE, XISF_PAGES8_PER_BLOCK,
	XISF_BLOCKS32_PER_SECTOR, XISF_NUM_OF_SECTORS8},

	{XISF_ATMEL_DEV_AT45DB081D, XISF_BYTES264_PER_PAGE,
	XISF_BYTES256_PER_PAGE, XISF_PAGES8_PER_BLOCK,
	XISF_BLOCKS32_PER_SECTOR, XISF_NUM_OF_SECTORS16},

	{XISF_ATMEL_DEV_AT45DB161D, XISF_BYTES528_PER_PAGE,
	XISF_BYTES512_PER_PAGE, XISF_PAGES8_PER_BLOCK,
	XISF_BLOCKS32_PER_SECTOR, XISF_NUM_OF_SECTORS16},

	{XISF_ATMEL_DEV_AT45DB321D, XISF_BYTES528_PER_PAGE,
	XISF_BYTES512_PER_PAGE, XISF_PAGES8_PER_BLOCK,
	XISF_BLOCKS16_PER_SECTOR, XISF_NUM_OF_SECTORS64},

	{XISF_ATMEL_DEV_AT45DB642D, XISF_BYTES1056_PER_PAGE,
	XISF_BYTES1024_PER_PAGE, XISF_PAGES8_PER_BLOCK,
	XISF_BLOCKS32_PER_SECTOR, XISF_NUM_OF_SECTORS32}
};
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */

#if (((XPAR_XISF_FLASH_FAMILY == INTEL) || \
	(XPAR_XISF_FLASH_FAMILY == STM) || \
	(XPAR_XISF_FLASH_FAMILY == SST) || \
	(XPAR_XISF_FLASH_FAMILY == WINBOND) || \
	(XPAR_XISF_FLASH_FAMILY == SPANSION)) && \
	((!defined(XPAR_XISF_INTERFACE_PSQSPI)) && \
	(!defined(XPAR_XISF_INTERFACE_QSPIPSU)) && \
	(!defined(XPAR_XISF_INTERFACE_OSPIPSV))))
static const struct IntelStmDeviceGeometry IntelStmDevices[] = {
	{XISF_MANUFACTURER_ID_INTEL, XISF_INTEL_DEV_S3316MBIT,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS32},

	{XISF_MANUFACTURER_ID_INTEL, XISF_INTEL_DEV_S3332MBIT,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS64},

	{XISF_MANUFACTURER_ID_INTEL, XISF_INTEL_DEV_S3364MBIT,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS128},

	{XISF_MANUFACTURER_ID_STM, XISF_STM_DEV_M25P05_A,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES128_PER_SECTOR,
	 XISF_NUM_OF_SECTORS2},

	{XISF_MANUFACTURER_ID_STM, XISF_STM_DEV_M25P10_A,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS2},

	{XISF_MANUFACTURER_ID_STM, XISF_STM_DEV_M25P20,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS4},

	{XISF_MANUFACTURER_ID_STM, XISF_STM_DEV_M25P40,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS8},

	{XISF_MANUFACTURER_ID_STM, XISF_STM_DEV_M25P80,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS16},

	{XISF_MANUFACTURER_ID_STM, XISF_STM_DEV_M25P16,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS32},

	{XISF_MANUFACTURER_ID_STM, XISF_STM_DEV_M25P32,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS64},

	{XISF_MANUFACTURER_ID_STM, XISF_STM_DEV_M25P64,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS128},

	{XISF_MANUFACTURER_ID_STM, XISF_STM_DEV_M25P128,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES1024_PER_SECTOR,
	 XISF_NUM_OF_SECTORS64},

	{XISF_MANUFACTURER_ID_WINBOND, XISF_WB_DEV_W25Q80,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES16_PER_SECTOR,
	 XISF_NUM_OF_SECTORS256},

	{XISF_MANUFACTURER_ID_WINBOND, XISF_WB_DEV_W25Q16,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES16_PER_SECTOR,
	 XISF_NUM_OF_SECTORS512},

	{XISF_MANUFACTURER_ID_WINBOND, XISF_WB_DEV_W25Q32,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES16_PER_SECTOR,
	 XISF_NUM_OF_SECTORS1024},

	{XISF_MANUFACTURER_ID_WINBOND, XISF_WB_DEV_W25Q64,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES16_PER_SECTOR,
	 XISF_NUM_OF_SECTORS2048},

	{XISF_MANUFACTURER_ID_WINBOND, XISF_WB_DEV_W25Q128,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES16_PER_SECTOR,
	 XISF_NUM_OF_SECTORS4096},

	{XISF_MANUFACTURER_ID_WINBOND, XISF_WB_DEV_W25X10,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES16_PER_SECTOR,
	 XISF_NUM_OF_SECTORS32},

	{XISF_MANUFACTURER_ID_WINBOND, XISF_WB_DEV_W25X20,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES16_PER_SECTOR,
	 XISF_NUM_OF_SECTORS64},

	{XISF_MANUFACTURER_ID_WINBOND, XISF_WB_DEV_W25X40,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES16_PER_SECTOR,
	 XISF_NUM_OF_SECTORS128},

	{XISF_MANUFACTURER_ID_WINBOND, XISF_WB_DEV_W25X80,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES16_PER_SECTOR,
	 XISF_NUM_OF_SECTORS256},

	{XISF_MANUFACTURER_ID_WINBOND, XISF_WB_DEV_W25X16,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES16_PER_SECTOR,
	 XISF_NUM_OF_SECTORS512},

	{XISF_MANUFACTURER_ID_WINBOND, XISF_WB_DEV_W25X32,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES16_PER_SECTOR,
	 XISF_NUM_OF_SECTORS1024},

	{XISF_MANUFACTURER_ID_WINBOND, XISF_WB_DEV_W25X64,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES16_PER_SECTOR,
	 XISF_NUM_OF_SECTORS2048},

	{XISF_MANUFACTURER_ID_STM, XISF_NM_DEV_N25Q32,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS64},

	{XISF_MANUFACTURER_ID_STM, XISF_NM_DEV_N25Q64,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS128},

	{XISF_MANUFACTURER_ID_STM, XISF_NM_DEV_N25Q128,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS256},

	{XISF_MANUFACTURER_ID_STM, XISF_MIC_DEV_N25Q128,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS256},

	{XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_DEV_S25FL004,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS8},

	{XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_DEV_S25FL008,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS16},

	{XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_DEV_S25FL016,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS32},

	{XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_DEV_S25FL032,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS64},

	{XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_DEV_S25FL064,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS128},

	{XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_DEV_S25FL064L,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS128},

	{XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_DEV_S25FL128,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS256},

	{XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_DEV_S25FL128L,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS256},

	 {XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_DEV_S25FL256,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS512},

	 {XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_DEV_S25FL256L,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS512},

	 {XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_DEV_S25FL512,
	 XISF_BYTES512_PER_PAGE, XISF_PAGES512_PER_SECTOR,
	 XISF_NUM_OF_SECTORS256},

	{XISF_MANUFACTURER_ID_SST, XISF_SST_DEV_SST25WF080,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS256},

	 {XISF_MANUFACTURER_ID_SST, XISF_SST_DEV_SST26WF016B,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS512},

	{XISF_MANUFACTURER_ID_MICRON, XISF_MIC_DEV_N25Q256_3V0,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS512},

	{XISF_MANUFACTURER_ID_MICRON, XISF_MIC_DEV_N25Q256_1V8,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS512},

	{XISF_MANUFACTURER_ID_MICRON, XISF_MIC_DEV_MT25Q512_3V0,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS1024},

	{XISF_MANUFACTURER_ID_MICRON, XISF_MIC_DEV_MT25Q512_1V8,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS1024},

	 {XISF_MANUFACTURER_ID_MICRON, XISF_MIC_DEV_MT25Q01_3V0,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS2048},

	 {XISF_MANUFACTURER_ID_MICRON, XISF_MIC_DEV_MT25Q01_1V8,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS2048},

	 {XISF_MANUFACTURER_ID_MICRON, XISF_MIC_DEV_MT25Q02_3V0,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS4096},

	 {XISF_MANUFACTURER_ID_MICRON, XISF_MIC_DEV_MT25Q02_1V8,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS4096},

	 {XISF_MANUFACTURER_ID_ISSI, XISF_ISSI_DEV_IS25WP080D,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS16},

	 {XISF_MANUFACTURER_ID_ISSI, XISF_ISSI_DEV_IS25LP080D,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS16},

	 {XISF_MANUFACTURER_ID_ISSI, XISF_ISSI_DEV_IS25WP016D,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS32},

	 {XISF_MANUFACTURER_ID_ISSI, XISF_ISSI_DEV_IS25LP016D,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS32},

	 {XISF_MANUFACTURER_ID_ISSI, XISF_ISSI_DEV_IS25WP032D,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS64},

	 {XISF_MANUFACTURER_ID_ISSI, XISF_ISSI_DEV_IS25LP032D,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS64},

	 {XISF_MANUFACTURER_ID_ISSI, XISF_ISSI_DEV_IS25WP064A,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS128},

	 {XISF_MANUFACTURER_ID_ISSI, XISF_ISSI_DEV_IS25LP064A,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS128},

	 {XISF_MANUFACTURER_ID_ISSI, XISF_ISSI_DEV_IS25LP128F,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS256},

	 {XISF_MANUFACTURER_ID_ISSI, XISF_ISSI_DEV_IS25WP128F,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS256},

	 {XISF_MANUFACTURER_ID_ISSI, XISF_ISSI_DEV_IS25WP256D,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS512},

	 {XISF_MANUFACTURER_ID_ISSI, XISF_ISSI_DEV_IS25LP256D,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS512},

	 {XISF_MANUFACTURER_ID_ISSI, XISF_ISSI_DEV_IS25LP512M,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS1024},

	 {XISF_MANUFACTURER_ID_ISSI, XISF_ISSI_DEV_IS25WP512M,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS1024},

	 {XISF_MANUFACTURER_ID_MACRONIX, XISF_MACRONIX_DEV_MX66U1G45G,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS2048},

	 {XISF_MANUFACTURER_ID_MACRONIX, XISF_MACRONIX_DEV_MX66L1G45G,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS2048},

	 {XISF_MANUFACTURER_ID_MACRONIX, XISF_MACRONIX_DEV_MX66L1G55G,
	 XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR,
	 XISF_NUM_OF_SECTORS2048},
};
#endif
/**
 * (((XPAR_XISF_FLASH_FAMILY==INTEL) || \
 * (XPAR_XISF_FLASH_FAMILY==STM) || \
 * (XPAR_XISF_FLASH_FAMILY == SST) || \
 * (XPAR_XISF_FLASH_FAMILY == WINBOND) || \
 * (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \
 * ((!defined(XPAR_XISF_INTERFACE_PSQSPI)) && \
 * (!defined(XPAR_XISF_INTERFACE_QSPIPSU)) && \
 * (!defined(XPAR_XISF_INTERFACE_OSPIPSV))))
 */

#if (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \
	(XPAR_XISF_FLASH_FAMILY == SPANSION)) && \
	(defined(XPAR_XISF_INTERFACE_PSQSPI) || \
	defined(XPAR_XISF_INTERFACE_QSPIPSU)))
static const struct SpaMicWinDeviceGeometry SpaMicWinDevices[] = {
	{0x10000, XISF_NUM_OF_SECTORS256, XISF_PAGES256_PER_SECTOR, 0x10000,
		0x1000000, XISF_MANUFACTURER_ID_SPANSION,
		XISF_SPANSION_ID_BYTE2_128, 0xFFFF0000, 1},
	{0x10000, XISF_NUM_OF_SECTORS512, XISF_PAGES256_PER_SECTOR, 0x20000,
		0x1000000, XISF_MANUFACTURER_ID_SPANSION,
		XISF_SPANSION_ID_BYTE2_128, 0xFFFF0000, 1},
	{0x20000, XISF_NUM_OF_SECTORS256, XISF_PAGES512_PER_SECTOR, 0x10000,
		0x1000000, XISF_MANUFACTURER_ID_SPANSION,
		XISF_SPANSION_ID_BYTE2_128, 0xFFFE0000, 1},
	{0x10000, XISF_NUM_OF_SECTORS512, XISF_PAGES256_PER_SECTOR, 0x20000,
		0x2000000, XISF_MANUFACTURER_ID_SPANSION,
		XISF_SPANSION_ID_BYTE2_256, 0xFFFF0000, 1},
	{0x10000, XISF_NUM_OF_SECTORS1024, XISF_PAGES256_PER_SECTOR, 0x40000,
		0x2000000, XISF_MANUFACTURER_ID_SPANSION,
		XISF_SPANSION_ID_BYTE2_256, 0xFFFF0000, 1},
	{0x20000, XISF_NUM_OF_SECTORS512, XISF_PAGES512_PER_SECTOR, 0x20000,
		0x2000000, XISF_MANUFACTURER_ID_SPANSION,
		XISF_SPANSION_ID_BYTE2_256, 0xFFFE0000, 1},
	{0x40000, XISF_NUM_OF_SECTORS256, XISF_PAGES512_PER_SECTOR, 0x20000,
		0x4000000, XISF_MANUFACTURER_ID_SPANSION,
		XISF_SPANSION_ID_BYTE2_512, 0xFFFC0000, 1},
	{0x40000, XISF_NUM_OF_SECTORS512, XISF_PAGES512_PER_SECTOR, 0x40000,
		0x4000000, XISF_MANUFACTURER_ID_SPANSION,
		XISF_SPANSION_ID_BYTE2_512, 0xFFFC0000, 1},
	{0x80000, XISF_NUM_OF_SECTORS256, XISF_PAGES1024_PER_SECTOR, 0x20000,
		0x4000000, XISF_MANUFACTURER_ID_SPANSION,
		XISF_SPANSION_ID_BYTE2_512, 0xFFF80000, 1},
	/* Spansion 1Gbit is handled as 512Mbit stacked */
	/* Micron */
	{0x10000, XISF_NUM_OF_SECTORS256, XISF_PAGES256_PER_SECTOR, 0x10000,
		0x1000000, XISF_MANUFACTURER_ID_MICRON,
		XISF_MICRON_ID_BYTE2_128, 0xFFFF0000, 1},
	{0x10000, XISF_NUM_OF_SECTORS512, XISF_PAGES256_PER_SECTOR, 0x20000,
		0x1000000, XISF_MANUFACTURER_ID_MICRON,
		XISF_MICRON_ID_BYTE2_128, 0xFFFF0000, 1},
	{0x20000, XISF_NUM_OF_SECTORS256, XISF_PAGES512_PER_SECTOR, 0x10000,
		0x1000000, XISF_MANUFACTURER_ID_MICRON,
		XISF_MICRON_ID_BYTE2_128, 0xFFFE0000, 1},
	{0x10000, XISF_NUM_OF_SECTORS512, XISF_PAGES256_PER_SECTOR, 0x20000,
		0x2000000, XISF_MANUFACTURER_ID_MICRON,
		XISF_MICRON_ID_BYTE2_256, 0xFFFF0000, 1},
	{0x10000, XISF_NUM_OF_SECTORS1024, XISF_PAGES256_PER_SECTOR, 0x40000,
		0x2000000, XISF_MANUFACTURER_ID_MICRON,
		XISF_MICRON_ID_BYTE2_256, 0xFFFF0000, 1},
	{0x20000, XISF_NUM_OF_SECTORS512, XISF_PAGES512_PER_SECTOR, 0x20000,
		0x2000000, XISF_MANUFACTURER_ID_MICRON,
		XISF_MICRON_ID_BYTE2_256, 0xFFFE0000, 1},
	{0x10000, XISF_NUM_OF_SECTORS1024, XISF_PAGES256_PER_SECTOR, 0x40000,
		0x4000000, XISF_MANUFACTURER_ID_MICRON,
		XISF_MICRON_ID_BYTE2_512, 0xFFFF0000, 2},
	{0x10000, XISF_NUM_OF_SECTORS2048, XISF_PAGES256_PER_SECTOR, 0x80000,
		0x4000000, XISF_MANUFACTURER_ID_MICRON,
		XISF_MICRON_ID_BYTE2_512, 0xFFFF0000, 2},
	{0x20000, XISF_NUM_OF_SECTORS1024, XISF_PAGES512_PER_SECTOR, 0x40000,
		0x4000000, XISF_MANUFACTURER_ID_MICRON,
		XISF_MICRON_ID_BYTE2_512, 0xFFFE0000, 2},
	{0x10000, XISF_NUM_OF_SECTORS2048, XISF_PAGES256_PER_SECTOR, 0x80000,
		0x8000000, XISF_MANUFACTURER_ID_MICRON,
		XISF_MICRON_ID_BYTE2_1G, 0xFFFF0000, 4},
	{0x10000, XISF_NUM_OF_SECTORS4096, XISF_PAGES256_PER_SECTOR, 0x100000,
		0x8000000, XISF_MANUFACTURER_ID_MICRON,
		XISF_MICRON_ID_BYTE2_1G, 0xFFFF0000, 4},
	{0x20000, XISF_NUM_OF_SECTORS2048, XISF_PAGES512_PER_SECTOR, 0x80000,
		0x8000000, XISF_MANUFACTURER_ID_MICRON,
		XISF_MICRON_ID_BYTE2_1G, 0xFFFE0000, 4},
	/* Winbond */
	{0x10000, XISF_NUM_OF_SECTORS256, XISF_PAGES256_PER_SECTOR, 0x10000,
		0x1000000, XISF_MANUFACTURER_ID_WINBOND,
		XISF_WINBOND_ID_BYTE2_128, 0xFFFF0000, 1},
	{0x10000, XISF_NUM_OF_SECTORS512, XISF_PAGES256_PER_SECTOR, 0x20000,
		0x1000000, XISF_MANUFACTURER_ID_WINBOND,
		XISF_WINBOND_ID_BYTE2_128, 0xFFFF0000, 1},
	{0x20000, XISF_NUM_OF_SECTORS256, XISF_PAGES512_PER_SECTOR, 0x10000,
		0x1000000, XISF_MANUFACTURER_ID_WINBOND,
		XISF_WINBOND_ID_BYTE2_128, 0xFFFE0000, 1},
	/* ISSI */
	{0x10000, XISF_NUM_OF_SECTORS16, XISF_PAGES256_PER_SECTOR, 0x1000,
		0x100000, XISF_MANUFACTURER_ID_ISSI,
		XISF_ISSI_ID_BYTE2_08, 0xFFFF0000, 1},
	{0x10000, XISF_NUM_OF_SECTORS32, XISF_PAGES256_PER_SECTOR, 0x2000,
		0x100000, XISF_MANUFACTURER_ID_ISSI,
		XISF_ISSI_ID_BYTE2_08, 0xFFFF0000, 1},
	{0x20000, XISF_NUM_OF_SECTORS16, XISF_PAGES512_PER_SECTOR, 0x1000,
		0x100000, XISF_MANUFACTURER_ID_ISSI,
		XISF_ISSI_ID_BYTE2_08, 0xFFFF0000, 1},
	{0x10000, XISF_NUM_OF_SECTORS32, XISF_PAGES256_PER_SECTOR, 0x2000,
		0x200000, XISF_MANUFACTURER_ID_ISSI,
		XISF_ISSI_ID_BYTE2_16, 0xFFFF0000, 1},
	{0x10000, XISF_NUM_OF_SECTORS64, XISF_PAGES256_PER_SECTOR, 0x4000,
		0x200000, XISF_MANUFACTURER_ID_ISSI,
		XISF_ISSI_ID_BYTE2_16, 0xFFFF0000, 1},
	{0x20000, XISF_NUM_OF_SECTORS32, XISF_PAGES512_PER_SECTOR, 0x2000,
		0x200000, XISF_MANUFACTURER_ID_ISSI,
		XISF_ISSI_ID_BYTE2_16, 0xFFFF0000, 1},
	{0x10000, XISF_NUM_OF_SECTORS64, XISF_PAGES256_PER_SECTOR, 0x4000,
		0x400000, XISF_MANUFACTURER_ID_ISSI,
		XISF_ISSI_ID_BYTE2_32, 0xFFFF0000, 1},
	{0x10000, XISF_NUM_OF_SECTORS128, XISF_PAGES256_PER_SECTOR, 0x80000,
		0x400000, XISF_MANUFACTURER_ID_ISSI,
		XISF_ISSI_ID_BYTE2_32, 0xFFFF0000, 1},
	{0x20000, XISF_NUM_OF_SECTORS64, XISF_PAGES512_PER_SECTOR, 0x4000,
		0x400000, XISF_MANUFACTURER_ID_ISSI,
		XISF_ISSI_ID_BYTE2_32, 0xFFFF0000, 1},
	{0x10000, XISF_NUM_OF_SECTORS128, XISF_PAGES256_PER_SECTOR, 0x8000,
		0x800000, XISF_MANUFACTURER_ID_ISSI,
		XISF_ISSI_ID_BYTE2_64, 0xFFFF0000, 1},
	{0x10000, XISF_NUM_OF_SECTORS256, XISF_PAGES256_PER_SECTOR, 0x10000,
		0x800000, XISF_MANUFACTURER_ID_ISSI,
		XISF_ISSI_ID_BYTE2_64, 0xFFFF0000, 1},
	{0x20000, XISF_NUM_OF_SECTORS128, XISF_PAGES512_PER_SECTOR, 0x8000,
		0x800000, XISF_MANUFACTURER_ID_ISSI,
		XISF_ISSI_ID_BYTE2_64, 0xFFFF0000, 1},
	{0x10000, XISF_NUM_OF_SECTORS256, XISF_PAGES256_PER_SECTOR, 0x10000,
		0x1000000, XISF_MANUFACTURER_ID_ISSI,
		XISF_ISSI_ID_BYTE2_128, 0xFFFF0000, 1},
	{0x10000, XISF_NUM_OF_SECTORS512, XISF_PAGES256_PER_SECTOR, 0x20000,
		0x1000000, XISF_MANUFACTURER_ID_ISSI,
		XISF_ISSI_ID_BYTE2_128, 0xFFFF0000, 1},
	{0x20000, XISF_NUM_OF_SECTORS256, XISF_PAGES512_PER_SECTOR, 0x10000,
		0x1000000, XISF_MANUFACTURER_ID_ISSI,
		XISF_ISSI_ID_BYTE2_128, 0xFFFE0000, 1},
	{0x10000, XISF_NUM_OF_SECTORS512, XISF_PAGES256_PER_SECTOR, 0x20000,
		0x2000000, XISF_MANUFACTURER_ID_ISSI,
		XISF_ISSI_ID_BYTE2_256, 0xFFFF0000, 1},
	{0x10000, XISF_NUM_OF_SECTORS1024, XISF_PAGES256_PER_SECTOR, 0x40000,
		0x2000000, XISF_MANUFACTURER_ID_ISSI,
		XISF_ISSI_ID_BYTE2_256, 0xFFFF0000, 1},
	{0x20000, XISF_NUM_OF_SECTORS512, XISF_PAGES512_PER_SECTOR, 0x20000,
		0x2000000, XISF_MANUFACTURER_ID_ISSI,
		XISF_ISSI_ID_BYTE2_256, 0xFFFF0000, 1},
	{0x10000, XISF_NUM_OF_SECTORS1024, XISF_PAGES256_PER_SECTOR, 0x40000,
		0x4000000, XISF_MANUFACTURER_ID_ISSI,
		XISF_ISSI_ID_BYTE2_512, 0xFFFF0000, 2},
	{0x10000, XISF_NUM_OF_SECTORS2048, XISF_PAGES256_PER_SECTOR, 0x80000,
		0x4000000, XISF_MANUFACTURER_ID_ISSI,
		XISF_ISSI_ID_BYTE2_512, 0xFFFF0000, 2},
	{0x20000, XISF_NUM_OF_SECTORS1024, XISF_PAGES512_PER_SECTOR, 0x40000,
		0x4000000, XISF_MANUFACTURER_ID_ISSI,
		XISF_ISSI_ID_BYTE2_512, 0xFFFE0000, 2},
	/* Macronix*/
	{0x10000, XISF_NUM_OF_SECTORS2048, XISF_PAGES256_PER_SECTOR, 0x80000,
		0x8000000, XISF_MANUFACTURER_ID_MACRONIX,
		XISF_MACRONIX_ID_BYTE2_1G, 0xFFFF0000, 4},
	{0x10000, XISF_NUM_OF_SECTORS4096, XISF_PAGES256_PER_SECTOR, 0x100000,
		0x8000000, XISF_MANUFACTURER_ID_MACRONIX,
		XISF_MACRONIX_ID_BYTE2_1G, 0xFFFF0000, 4},
	{0x20000, XISF_NUM_OF_SECTORS2048, XISF_PAGES512_PER_SECTOR, 0x80000,
		0x8000000, XISF_MANUFACTURER_ID_MACRONIX,
		XISF_MACRONIX_ID_BYTE2_1G, 0xFFFE0000, 4},
	{0x10000, XISF_NUM_OF_SECTORS2048, XISF_PAGES256_PER_SECTOR, 0x80000,
		0x8000000, XISF_MANUFACTURER_ID_MACRONIX,
		XISF_MACRONIX_ID_BYTE2_1GU, 0xFFFF0000, 4},
	{0x10000, XISF_NUM_OF_SECTORS4096, XISF_PAGES256_PER_SECTOR, 0x100000,
		0x8000000, XISF_MANUFACTURER_ID_MACRONIX,
		XISF_MACRONIX_ID_BYTE2_1GU, 0xFFFF0000, 4},
	{0x20000, XISF_NUM_OF_SECTORS2048, XISF_PAGES512_PER_SECTOR, 0x80000,
		0x8000000, XISF_MANUFACTURER_ID_MACRONIX,
		XISF_MACRONIX_ID_BYTE2_1GU, 0xFFFE0000, 4},
};
#endif
/**
 * (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \
 * (XPAR_XISF_FLASH_FAMILY == SPANSION)) &&	\
 * (defined(XPAR_XISF_INTERFACE_PSQSPI) || \
 * defined(XPAR_XISF_INTERFACE_QSPIPSU)))
 */

#if (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \
	(XPAR_XISF_FLASH_FAMILY == SPANSION)) &&	\
	(defined(XPAR_XISF_INTERFACE_OSPIPSV)))
static const struct SpaMicWinDeviceGeometry SpaMicWinDevices[] = {
	{0x20000, XISF_NUM_OF_SECTORS512, XISF_PAGES256_PER_SECTOR, 0x40000,
		0x4000000, XISF_MANUFACTURER_ID_MICRON_OCTAL,
		XISF_MICRON_OCTAL_ID_BYTE2_512, 0xFFFF0000, 1}
};
#endif
/**
 * (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \
 * (XPAR_XISF_FLASH_FAMILY == SPANSION)) &&	\
 * (defined(XPAR_XISF_INTERFACE_OSPIPSV)))
 */

/*
 * The following variables are shared between non-interrupt processing and
 * interrupt processing such that they must be global.
 */
volatile unsigned int XIsf_TransferInProgress;
#if	(!defined(XPAR_XISF_INTERFACE_PSSPI))
static u32 XIsf_FCTIndex;
#endif
/************************** Function Definitions *****************************/

/*****************************************************************************/
/**
 * @brief
 * This API when called initializes the SPI interface with default settings.
 * With custom settings, user should call XIsf_SetSpiConfiguration() and then
 * call this API.
 * The geometry of the underlying Serial Flash is determined by reading the
 * Joint Electron Device Engineering Council (JEDEC) Device Information and
 * the Status Register of the Serial Flash.
 *
 * @param	InstancePtr	Pointer to the XIsf instance.
 * @param	SpiInstPtr	Pointer to XIsf_Iface instance to be worked on.
 * @param	SlaveSelect	It is a 32-bit mask with a 1 in the bit
 *				position of slave being selected. Only one
 *				slave can be selected at a time.
 * @param	WritePtr	Pointer to the buffer allocated by the user
 *				to be used by the In-system and Serial Flash
 *				Library to perform any read/write operations
 *				on the Serial Flash device.
 *				User applications must pass the address of this
 *				buffer for the Library to work.
 *				- Write operations :
 *				   - The size of this buffer should be equal
 *				   to the Number of bytes to be written to
 *				   the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
 *				   - The size of this buffer should be large
 *				   enough for usage across all the applications
 *				   that use a common instance of the Serial
 *				   Flash.
 *				   - A minimum of one byte and a maximum of
 *				   ISF_PAGE_SIZE bytes can be written to the
 *				   Serial Flash, through a single Write
 *				   operation.
 *               - Read operations :
 *                  - The size of this buffer should be equal
 *                  to XISF_CMD_MAX_EXTRA_BYTES, if the
 *                  application only reads from the Serial Flash
 *                  (no write operations).
 *
 * @return	- XST_SUCCESS if successful.
 *		- XST_DEVICE_IS_STOPPED if the device must be started before
 *		transferring data.
 *		- XST_FAILURE, otherwise.
 *
 * @note		- The XIsf_Initialize() API is a blocking call (for both
 *		polled and interrupt modes of the Spi driver). It reads the
 *		JEDEC information of the device and waits till the transfer is
 *		complete before checking if the information is valid.
 *		- This library can support multiple instances of Serial Flash
 *		at a time, provided they are of the same device family (either
 *		Atmel, Intel or STM, Winbond or Spansion) as the device family
 *		is selected at compile time.
 *
 ******************************************************************************/
int XIsf_Initialize(XIsf *InstancePtr, XIsf_Iface *SpiInstPtr, u8 SlaveSelect,
				u8 *WritePtr)
{
	int Status = (int)(XST_FAILURE);
	u8 ReadBuf[XISF_INFO_READ_BYTES + XISF_INFO_EXTRA_BYTES] __attribute__ ((aligned(4))) = {0};

	if (InstancePtr == NULL)
		return (int)(XST_FAILURE);

	if (SpiInstPtr == NULL)
		return (int)(XST_FAILURE);

	if (WritePtr == NULL)
		return (int)(XST_FAILURE);

	InstancePtr->IsReady = FALSE;
	InstancePtr->SpiSlaveSelect = SlaveSelect;
	InstancePtr->WriteBufPtr = WritePtr;

#ifdef XPAR_XISF_INTERFACE_AXISPI
	if (SpiInstPtr->IsStarted != XIL_COMPONENT_IS_STARTED)
		return XST_DEVICE_IS_STOPPED;
#endif

	if ((!InstancePtr->RegDone) != 0)
		(void)XIsf_SetSpiConfiguration(InstancePtr, SpiInstPtr,
				XISF_SPI_OPTIONS, XISF_SPI_PRESCALER);

#ifdef XPAR_XISF_INTERFACE_OSPIPSV
	InstancePtr->XIsf_Iface_SetSlaveSelect(InstancePtr->SpiInstPtr,
			InstancePtr->SpiSlaveSelect);
#endif

	/*
	 * Get the JEDEC Device Info.
	 * The IsReady is temporarily made TRUE and
	 * transfer is set in polling mode to fetch the JEDEC Info.
	 */
	XIsf_SetTransferMode(InstancePtr, XISF_POLLING_MODE);
	InstancePtr->IsReady = TRUE;
	Status = XIsf_GetDeviceInfo(InstancePtr, ReadBuf);
	InstancePtr->IsReady = FALSE;
	if (Status != (int)(XST_SUCCESS))
		return (int)(XST_FAILURE);

#ifdef XPAR_XISF_INTERFACE_AXISPI
	/*
	 * Wait until the transfer is complete.
	 */
	do {
		Status =
		InstancePtr->XIsf_Iface_SetSlaveSelect(InstancePtr->SpiInstPtr,
					InstancePtr->SpiSlaveSelect);
	} while (Status == XST_DEVICE_BUSY);

	if (Status != (int)(XST_SUCCESS))
		return (int)(XST_FAILURE);

#endif

#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
	/*
	 * Check for Atmel Serial Flash.
	 */
	Status = AtmelFlashInitialize(InstancePtr, ReadBuf);

#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */

#if (((XPAR_XISF_FLASH_FAMILY == INTEL) || \
	(XPAR_XISF_FLASH_FAMILY == STM) || \
	(XPAR_XISF_FLASH_FAMILY == SST) || \
	(XPAR_XISF_FLASH_FAMILY == WINBOND) || \
	(XPAR_XISF_FLASH_FAMILY == SPANSION)) && \
	((!defined(XPAR_XISF_INTERFACE_PSQSPI)) && \
	(!defined(XPAR_XISF_INTERFACE_QSPIPSU)) && \
	(!defined(XPAR_XISF_INTERFACE_OSPIPSV))))

	/*
	 * Check for Intel/STM/Winbond/Spansion Serial Flash.
	 */
	Status = IntelStmFlashInitialize(InstancePtr, ReadBuf);

#endif
/**
 * (((XPAR_XISF_FLASH_FAMILY==INTEL) || \
 * (XPAR_XISF_FLASH_FAMILY==STM) || \
 * (XPAR_XISF_FLASH_FAMILY == SST) || \
 * (XPAR_XISF_FLASH_FAMILY == WINBOND) || \
 * (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \
 * ((!defined(XPAR_XISF_INTERFACE_PSQSPI)) && \
 * (!defined(XPAR_XISF_INTERFACE_QSPIPSU)) && \
 * (!defined(XPAR_XISF_INTERFACE_OSPIPSV))))
 */
#if (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \
	(XPAR_XISF_FLASH_FAMILY == SPANSION)) && \
	(defined(XPAR_XISF_INTERFACE_PSQSPI) || \
	defined(XPAR_XISF_INTERFACE_QSPIPSU) || \
	defined(XPAR_XISF_INTERFACE_OSPIPSV)))

	Status = SpaMicWinFlashInitialize(InstancePtr, ReadBuf);

#endif
/**
 * (((XPAR_XISF_FLASH_FAMILY == WINBOND) ||	\
 * (XPAR_XISF_FLASH_FAMILY == SPANSION)) &&	\
 * (defined(XPAR_XISF_INTERFACE_PSQSPI) || \
 * defined(XPAR_XISF_INTERFACE_QSPIPSU) || \
 * defined(XPAR_XISF_INTERFACE_OSPIPSV)))
 */

	return Status;
}


/*****************************************************************************/
/**
 * @brief
 * This API sets the configuration of SPI.  This will set the options and
 * clock prescaler (if applicable).
 *
 * @param	InstancePtr	Pointer to the XIsf instance.
 * @param	SpiInstPtr	Pointer to XIsf_Iface instance to be worked on.
 * @param	Options		Specified options to be set.
 * @param	PreScaler	Value of the clock prescaler to set.
 *
 * @return
 *		- XST_SUCCESS if successful.
 *		- XST_FAILURE if it fails.
 *
 * @note		This API can be called before calling XIsf_Initialize()
 *		to initialize the SPI interface in other than default options
 *		mode. PreScaler is only applicable to PS SPI/QSPI.
 *
 ******************************************************************************/
int XIsf_SetSpiConfiguration(XIsf *InstancePtr, XIsf_Iface *SpiInstPtr,
				u32 Options, u8 PreScaler)
{
	int Status = (int)(XST_FAILURE);

	if ((!InstancePtr->RegDone) != 0) {
		XIsf_RegisterInterface(InstancePtr);
		InstancePtr->SpiInstPtr = SpiInstPtr;
		InstancePtr->RegDone = TRUE;
	}

	Status = InstancePtr->XIsf_Iface_SetOptions(InstancePtr->SpiInstPtr,
						Options);
	if (Status != (int)(XST_SUCCESS))
		return (int)(XST_FAILURE);

	if ((InstancePtr->XIsf_Iface_SetClkPrescaler) != NULL) {
		Status = InstancePtr->XIsf_Iface_SetClkPrescaler(
				InstancePtr->SpiInstPtr, PreScaler);
		if (Status != (int)(XST_SUCCESS))
			return (int)(XST_FAILURE);
	}

	return (int)(XST_SUCCESS);
}


/*****************************************************************************/
/**
 * @brief
 * This API reads the Serial Flash Status Register.
 *
 * @param	InstancePtr	Pointer to the XIsf instance.
 * @param	ReadPtr		Pointer to the memory where the Status Register
 *				content is copied.
 *
 * @return
 *		- XST_SUCCESS if successful.
 *		- XST_FAILURE if it fails.
 *
 * @note	The contents of the Status Register is stored at second byte
 *		pointed by the ReadPtr.
 *
 ******************************************************************************/
int XIsf_GetStatus(XIsf *InstancePtr, u8 *ReadPtr)
{
	int Status = (int)(XST_FAILURE);
	u8 Mode;
#ifdef XPAR_XISF_INTERFACE_QSPIPSU
	u8 *NULLPtr = NULL;
#endif

	if (InstancePtr == NULL)
		return (int)(XST_FAILURE);

	if (InstancePtr->IsReady != TRUE)
		return (int)(XST_FAILURE);

	if (ReadPtr == NULL)
		return (int)(XST_FAILURE);

#ifndef XPAR_XISF_INTERFACE_QSPIPSU
	/*
	 * Prepare the Write Buffer.
	 */
	InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_STATUSREG_READ;
	InstancePtr->WriteBufPtr[BYTE2] = XISF_DUMMYBYTE;

	/*
	 * Initiate the Transfer.
	 */
	Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, ReadPtr,
				XISF_STATUS_RDWR_BYTES);
#else
	InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_STATUSREG_READ;
	FlashMsg[0].TxBfrPtr = InstancePtr->WriteBufPtr;
	FlashMsg[0].RxBfrPtr = NULL;
	FlashMsg[0].ByteCount = 1;
	FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
	FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;

	FlashMsg[1].TxBfrPtr = NULL;
	FlashMsg[1].RxBfrPtr = ReadPtr;
	FlashMsg[1].ByteCount = 2;
	FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
	FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX;
	if (InstancePtr->SpiInstPtr->Config.ConnectionMode ==
				XQSPIPSU_CONNECTION_MODE_PARALLEL)
		FlashMsg[1].Flags |= XQSPIPSU_MSG_FLAG_STRIPE;

	InstancePtr->SpiInstPtr->Msg = FlashMsg;
	/*
	 * Initiate the Transfer.
	 */
	Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, 2);
#endif

	/*
	 * Get the Transfer Mode
	 */
	Mode = XIsf_GetTransferMode(InstancePtr);

	if (Mode == XISF_INTERRUPT_MODE) {
#ifndef XPAR_XISF_INTERFACE_OSPIPSV
		InstancePtr->StatusHandler(InstancePtr,
				XIsf_StatusEventInfo, XIsf_ByteCountInfo);
#else
	InstancePtr->StatusHandler(InstancePtr, XIsf_StatusEventInfo);
#endif
	}

	if (Status != (int)(XST_SUCCESS))
		return (int)(XST_FAILURE);

	return (int)(XST_SUCCESS);
}

/*****************************************************************************/
/**
 * @brief
 * This API reads the Serial Flash Status Register 2.
 *
 * @param	InstancePtr	Pointer to the XIsf instance.
 * @param	ReadPtr		Pointer to the memory where the Status Register
 *				content is copied.
 *
 * @return
 *		- XST_SUCCESS if successful.
 *		- XST_FAILURE if it fails.
 *
 * @note	The contents of the Status Register 2 is stored at the second
 *		byte pointed by the ReadPtr.
 *		This operation is available only in Winbond Serial Flash.
 *
 ******************************************************************************/
#if (XPAR_XISF_FLASH_FAMILY == WINBOND)
int XIsf_GetStatusReg2(XIsf *InstancePtr, u8 *ReadPtr)
{
	int Status = (int)(XST_FAILURE);
	u8 Mode;
	u8 *NULLPtr = NULL;

	if (InstancePtr == NULL)
		return (int)(XST_FAILURE);

	if (InstancePtr->IsReady != TRUE)
		return (int)(XST_FAILURE);

	if (ReadPtr == NULL)
		return (int)(XST_FAILURE);

#ifndef XPAR_XISF_INTERFACE_QSPIPSU
	/*
	 * Prepare the Write Buffer.
	 */
	InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_STATUSREG2_READ;
	InstancePtr->WriteBufPtr[BYTE2] = XISF_DUMMYBYTE;

	/*
	 * Initiate the Transfer.
	 */
	Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, ReadPtr,
				XISF_STATUS_RDWR_BYTES);
#else
	InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_STATUSREG_READ;
	FlashMsg[0].TxBfrPtr = InstancePtr->WriteBufPtr;
	FlashMsg[0].RxBfrPtr = NULL;
	FlashMsg[0].ByteCount = 1;
	FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
	FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;

	FlashMsg[1].TxBfrPtr = NULL;
	FlashMsg[1].RxBfrPtr = ReadPtr;
	FlashMsg[1].ByteCount = 2;
	FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
	FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX;
	if (InstancePtr->SpiInstPtr->Config.ConnectionMode ==
				XQSPIPSU_CONNECTION_MODE_PARALLEL)
		FlashMsg[1].Flags |= XQSPIPSU_MSG_FLAG_STRIPE;

	InstancePtr->SpiInstPtr->Msg = FlashMsg;
	/*
	 * Initiate the Transfer.
	 */
	Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, 2);
#endif
	/*
	 * Get the Transfer Mode
	 */
	Mode = XIsf_GetTransferMode(InstancePtr);

	if (Mode == XISF_INTERRUPT_MODE)
		InstancePtr->StatusHandler(InstancePtr,
			XIsf_StatusEventInfo, XIsf_ByteCountInfo);

	if (Status != (int)(XST_SUCCESS))
		return (int)(XST_FAILURE);

	return (int)(XST_SUCCESS);
}
#endif

/*****************************************************************************/
/**
 * @brief
 * This API reads the Joint Electron Device Engineering Council (JEDEC)
 * information of the Serial Flash.
 *
 * @param	InstancePtr	Pointer to the XIsf instance.
 * @param	ReadPtr		Pointer to the buffer where the Device
 *				information is copied.
 *
 * @return
 *		- XST_SUCCESS if successful.
 *		- XST_FAILURE if it fails.
 *
 * @note	The Device information is stored at the second byte pointed
 *		by the ReadPtr.
 *
 ******************************************************************************/
int XIsf_GetDeviceInfo(XIsf *InstancePtr, u8 *ReadPtr)
{
	int Status = (int)(XST_FAILURE);
	u8 Mode;
#if (defined(XPAR_XISF_INTERFACE_QSPIPSU) || \
		defined(XPAR_XISF_INTERFACE_OSPIPSV))
	u8 *NULLPtr = NULL;
#endif

	if (InstancePtr == NULL)
		return (int)(XST_FAILURE);

	if (InstancePtr->IsReady != TRUE)
		return (int)(XST_FAILURE);

	if (ReadPtr == NULL)
		return (int)(XST_FAILURE);

#ifndef XPAR_XISF_INTERFACE_QSPIPSU
#ifdef XPAR_XISF_INTERFACE_OSPIPSV
	FlashMsg.Opcode = XISF_CMD_ISFINFO_READ;
	FlashMsg.Addrsize = 0;
	FlashMsg.Addrvalid = 0;
	FlashMsg.TxBfrPtr = NULL;
	FlashMsg.RxBfrPtr = ReadPtr;
	FlashMsg.ByteCount = 6;
	FlashMsg.Flags = XOSPIPSV_MSG_FLAG_RX;
	FlashMsg.Dummy = 0;
	FlashMsg.IsDDROpCode = 0;
	if (InstancePtr->SpiInstPtr->SdrDdrMode == XOSPIPSV_EDGE_MODE_DDR_PHY) {
		FlashMsg.Dummy = 8;
		FlashMsg.Proto = XOSPIPSV_READ_8_0_8;
	}
	InstancePtr->SpiInstPtr->Msg = &FlashMsg;
	/*
	 * Initiate the Transfer.
	 */
	Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, XISF_INFO_READ_BYTES);
#else
	/*
	 * Prepare the Write Buffer.
	 */
	InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_ISFINFO_READ;
	InstancePtr->WriteBufPtr[BYTE2] = XISF_DUMMYBYTE;
	InstancePtr->WriteBufPtr[BYTE3] = XISF_DUMMYBYTE;
	InstancePtr->WriteBufPtr[BYTE4] = XISF_DUMMYBYTE;
	InstancePtr->WriteBufPtr[BYTE5] = XISF_DUMMYBYTE;

	/*
	 * Initiate the Transfer.
	 */
	Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr,
				ReadPtr, XISF_INFO_READ_BYTES);
#endif
#else
	InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_ISFINFO_READ;
	FlashMsg[0].TxBfrPtr = InstancePtr->WriteBufPtr;
	FlashMsg[0].RxBfrPtr = NULL;
	FlashMsg[0].ByteCount = 1;
	FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
	FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;

	FlashMsg[1].TxBfrPtr = NULL;
	FlashMsg[1].RxBfrPtr = ReadPtr;
	FlashMsg[1].ByteCount = 5;
	FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
	FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX;
	InstancePtr->SpiInstPtr->Msg = FlashMsg;
	/*
	 * Initiate the Transfer.
	 */
	Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, 2);
#endif

	/*
	 * Get the Transfer Mode
	 */
	Mode = XIsf_GetTransferMode(InstancePtr);

	if (Mode == XISF_INTERRUPT_MODE) {
#ifndef XPAR_XISF_INTERFACE_OSPIPSV
		InstancePtr->StatusHandler(InstancePtr,
				XIsf_StatusEventInfo, XIsf_ByteCountInfo);
#else
	InstancePtr->StatusHandler(InstancePtr, XIsf_StatusEventInfo);
#endif
	}

	if (Status != (int)(XST_SUCCESS))
		return (int)(XST_FAILURE);

	return Status;
}

/*****************************************************************************/
/**
 * @brief
 * This API Enables/Disables writes to the Intel, STM, Winbond and Spansion
 * Serial Flash.
 *
 * @param	InstancePtr	Pointer to the XIsf instance.
 * @param	WriteEnable	Specifies whether to Enable
 *				(XISF_CMD_ENABLE_WRITE) or Disable
 *				(XISF_CMD_DISABLE_WRITE) the writes to the
 *				Serial Flash.
 *
 * @return
 *		- XST_SUCCESS if successful.
 *		- XST_FAILURE if it fails.
 *
 * @note	This API works only for Intel, STM, Winbond and Spansion Serial
 *		Flash. If this API is called for Atmel Flash, XST_FAILURE is
 *		returned.
 *
 ******************************************************************************/
int XIsf_WriteEnable(XIsf *InstancePtr, u8 WriteEnable)
{
	int Status = (int)(XST_FAILURE);
	u8 Mode;
	u8 WriteEnableBuf[1] = {0};
	u8 *NULLPtr = NULL;

#if ((XPAR_XISF_FLASH_FAMILY == INTEL) || (XPAR_XISF_FLASH_FAMILY == STM) || \
	(XPAR_XISF_FLASH_FAMILY == WINBOND) ||  \
	(XPAR_XISF_FLASH_FAMILY == SPANSION) || (XPAR_XISF_FLASH_FAMILY == SST))

	if (InstancePtr == NULL)
		return (int)(XST_FAILURE);

	if (InstancePtr->IsReady != TRUE)
		return (int)(XST_FAILURE);

	if (WriteEnable == XISF_WRITE_ENABLE)
		WriteEnableBuf[BYTE1] = XISF_CMD_ENABLE_WRITE;
	else if (WriteEnable == XISF_WRITE_DISABLE)
		WriteEnableBuf[BYTE1] = XISF_CMD_DISABLE_WRITE;
	else
		return Status;

	Xil_AssertNonvoid(NULLPtr == NULL);

#ifdef XPAR_XISF_INTERFACE_QSPIPSU
	FlashMsg[0].TxBfrPtr = WriteEnableBuf;
	FlashMsg[0].RxBfrPtr = NULL;
	FlashMsg[0].ByteCount = 1;
	FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
	FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
	InstancePtr->SpiInstPtr->Msg = FlashMsg;
	/*
	 * Initiate the Transfer.
	 */
	Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, 1);
#else
#ifdef XPAR_XISF_INTERFACE_OSPIPSV
	(void)WriteEnableBuf[BYTE1];
	FlashMsg.Opcode = XISF_CMD_ENABLE_WRITE;
	FlashMsg.Addrsize = 0;
	FlashMsg.Addrvalid = 0;
	FlashMsg.TxBfrPtr = NULL;
	FlashMsg.RxBfrPtr = NULL;
	FlashMsg.ByteCount = 0;
	FlashMsg.Flags = XOSPIPSV_MSG_FLAG_TX;
	FlashMsg.IsDDROpCode = 0;
	FlashMsg.Proto = 0;
	if (InstancePtr->SpiInstPtr->SdrDdrMode == XOSPIPSV_EDGE_MODE_DDR_PHY) {
		FlashMsg.Proto = XOSPIPSV_WRITE_8_0_0;
	}
	InstancePtr->SpiInstPtr->Msg = &FlashMsg;
	Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, FlashMsg.ByteCount);
#else
	/*
	 * Initiate the Transfer.
	 */
	Status = XIsf_Transfer(InstancePtr, WriteEnableBuf, NULLPtr,
				XISF_CMD_WRITE_ENABLE_DISABLE_BYTES);
#endif
#endif

	/*
	 * Get the Transfer Mode
	 */
	Mode = XIsf_GetTransferMode(InstancePtr);

	if (Mode == XISF_INTERRUPT_MODE) {
#ifndef XPAR_XISF_INTERFACE_OSPIPSV
		InstancePtr->StatusHandler(InstancePtr,
				XIsf_StatusEventInfo, XIsf_ByteCountInfo);
#else
	InstancePtr->StatusHandler(InstancePtr, XIsf_StatusEventInfo);
#endif
	}

#endif
/**
 * ((XPAR_XISF_FLASH_FAMILY==INTEL) || (XPAR_XISF_FLASH_FAMILY==STM) \
 * (XPAR_XISF_FLASH_FAMILY == WINBOND) ||	\
 * (XPAR_XISF_FLASH_FAMILY == SPANSION) ||	\
 * (XPAR_XISF_FLASH_FAMILY == SST))
 */

	return Status;
}

/*****************************************************************************/
/**
 * @brief
 * This API configures and controls the Intel, STM, Winbond and Spansion Serial
 * Flash.
 *
 * @param	InstancePtr	Pointer to the XIsf instance.
 * @param	Operation	Type of Control operation to be performed on
 *				the Serial Flash. The different control
 *				operations are
 *				- XISF_RELEASE_DPD: Release from Deep Power
 *				  Down (DPD) Mode
 *				- XISF_ENTER_DPD: Enter DPD Mode
 *				- XISF_CLEAR_SR_FAIL_FLAGS: Clear Status
 *				  Register Fail Flags
 *
 * @return
 *		- XST_SUCCESS if successful.
 *		- XST_FAILURE if i fails.
 *
 * @note
 *		- Atmel Serial Flash does not support any of these operations.
 *		- Intel Serial Flash support Enter/Release from DPD Mode and
 *		Clear Status Register Fail Flags.
 *		- STM, Winbond and Spansion Serial Flash support Enter/Release
 *		from DPD Mode.
 *		- Winbond (W25QXX) Serial Flash support Enable High Performance
 *		mode.
 *
 ******************************************************************************/
int XIsf_Ioctl(XIsf *InstancePtr, XIsf_IoctlOperation Operation)
{
	int Status = (int)(XST_FAILURE);
	u8 Mode;
	u8 *NULLPtr = NULL;

#if ((XPAR_XISF_FLASH_FAMILY == INTEL) || (XPAR_XISF_FLASH_FAMILY == STM) || \
	(XPAR_XISF_FLASH_FAMILY == WINBOND) || \
	(XPAR_XISF_FLASH_FAMILY == SPANSION) || (XPAR_XISF_FLASH_FAMILY == SST))
	u8 NumBytes;

	if (InstancePtr == NULL)
		return (int)(XST_FAILURE);

	if (InstancePtr->IsReady != TRUE)
		return (int)(XST_FAILURE);

	switch (Operation) {
	case XISF_IOCTL_RELEASE_DPD:
		InstancePtr->WriteBufPtr[BYTE1] =
			XISF_CMD_RELEASE_FROM_DPD;
		NumBytes = XISF_IOCTL_BYTES;
		break;

	case XISF_IOCTL_ENTER_DPD:
		InstancePtr->WriteBufPtr[BYTE1] =
			XISF_CMD_DEEP_POWER_DOWN;
		NumBytes = XISF_IOCTL_BYTES;
		break;

#if (XPAR_XISF_FLASH_FAMILY == INTEL)
	case XISF_IOCTL_CLEAR_SR_FAIL_FLAGS:
		InstancePtr->WriteBufPtr[BYTE1] =
			XISF_CMD_CLEAR_SRFAIL_FLAGS;
		NumBytes = XISF_IOCTL_BYTES;
		break;
#endif /* (XPAR_XISF_FLASH_FAMILY == INTEL) */

#if (XPAR_XISF_FLASH_FAMILY == WINBOND)
	case XISF_IOCTL_ENABLE_HI_PERF_MODE:
		InstancePtr->WriteBufPtr[BYTE1] =
			XISF_CMD_ENABLE_HPM;
		NumBytes = XISF_HPM_BYTES;
		break;
#endif /* (XPAR_XISF_FLASH_FAMILY == WINBOND) */

	default:
		return (int)(XST_FAILURE);
	}

	Xil_AssertNonvoid(NULLPtr == NULL);

#ifdef XPAR_XISF_INTERFACE_QSPIPSU
	FlashMsg[0].TxBfrPtr = InstancePtr->WriteBufPtr;
	FlashMsg[0].RxBfrPtr = NULL;
	FlashMsg[0].ByteCount = NumBytes;
	FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
	FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
	InstancePtr->SpiInstPtr->Msg = FlashMsg;
	/*
	 * Initiate the Transfer.
	 */
	Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, 1);
#else

	/*
	 * Initiate the Transfer.
	 */
	Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULLPtr,
				NumBytes);
#endif

	/*
	 * Get the Transfer Mode
	 */
	Mode = XIsf_GetTransferMode(InstancePtr);

	if (Mode == XISF_INTERRUPT_MODE) {
#ifndef XPAR_XISF_INTERFACE_OSPIPSV
		InstancePtr->StatusHandler(InstancePtr,
				XIsf_StatusEventInfo, XIsf_ByteCountInfo);
#else
		InstancePtr->StatusHandler(InstancePtr, XIsf_StatusEventInfo);
#endif
	}
#else
	Status = (int)(XST_FAILURE);

#endif
/**
 * ((XPAR_XISF_FLASH_FAMILY==INTEL) || (XPAR_XISF_FLASH_FAMILY==STM) \
 * (XPAR_XISF_FLASH_FAMILY == WINBOND) ||
 * (XPAR_XISF_FLASH_FAMILY == SPANSION))
 */

	return Status;
}

/*****************************************************************************/
/*
 *
 * This function performs the SPI transfer.
 *
 * @param	InstancePtr is a pointer to the XIsf instance.
 * @param	WritePtr is a pointer to the memory which contains the data to
 *		be transferred to the Serial Flash .
 * @param	ReadPtr is a pointer to the memory where the data read from the
 *		Serial Flash is stored.
 * @param	ByteCount is the number of bytes to be read from/written to the
 *		Serial Flash.
 *
 * @return	XST_SUCCESS if successful else XST_FAILURE.
 *
 * @note	This function is internal to the In-system and Serial Flash
 *		Library. It works with both interrupt mode and polled mode SPI
 *		transfers. In polled mode for AXI SPI, the user has to disable
 *		the Global Interrupts in the user application, after the Spi
 *		is Initialized and Spi driver is started
 *
 ******************************************************************************/
int XIsf_Transfer(XIsf *InstancePtr, u8 *WritePtr, u8 *ReadPtr, u32 ByteCount)
{
	int Status = (int)(XST_FAILURE);
#if (defined(XPAR_XISF_INTERFACE_QSPIPSU) || \
		defined(XPAR_XISF_INTERFACE_OSPIPSV))
	if (WritePtr != NULL || ReadPtr != NULL) {
		WritePtr = NULL;
		ReadPtr = NULL;
	}
#endif
#ifdef XPAR_XISF_INTERFACE_OSPIPSV
	(void)ByteCount;
#endif
	/*
	 * Select the Serial Flash as a slave.
	 */
#ifdef XPAR_XISF_INTERFACE_PSQSPI
	Status = InstancePtr->XIsf_Iface_SetSlaveSelect(
				InstancePtr->SpiInstPtr);
	if (Status != (int)(XST_SUCCESS))
		return (int)(XST_FAILURE);
#elif ((!defined(XPAR_XISF_INTERFACE_QSPIPSU)) && \
		(!defined(XPAR_XISF_INTERFACE_OSPIPSV)))
	Status = InstancePtr->XIsf_Iface_SetSlaveSelect(
				InstancePtr->SpiInstPtr,
				InstancePtr->SpiSlaveSelect);
	if (Status != (int)(XST_SUCCESS))
		return (int)(XST_FAILURE);
#endif

	/*
	 * Start the transfer.
	 */
#ifdef XPAR_XISF_INTERFACE_AXISPI
	if (InstancePtr->IntrMode == XISF_INTERRUPT_MODE)
		XIsf_TransferInProgress = TRUE;

	Status = InstancePtr->XIsf_Iface_Transfer(InstancePtr->SpiInstPtr,
			WritePtr, ReadPtr, ByteCount);
	if (Status != (int)(XST_SUCCESS))
		return (int)(XST_FAILURE);

	if (InstancePtr->IntrMode == XISF_INTERRUPT_MODE) {
		while (1) {
			if (XIsf_TransferInProgress == 0)
				break;
		}
	}

	return (int)(XST_SUCCESS);
#endif

	if (InstancePtr->IntrMode == XISF_INTERRUPT_MODE) {
#if defined(XPAR_XISF_INTERFACE_PSQSPI) || \
	defined(XPAR_XISF_INTERFACE_PSSPI) || \
	defined(XPAR_XISF_INTERFACE_QSPIPSU) || \
	defined(XPAR_XISF_INTERFACE_OSPIPSV)
		XIsf_TransferInProgress = TRUE;
#endif
#ifdef XPAR_XISF_INTERFACE_QSPIPSU
		Status = InstancePtr->XIsf_Iface_Transfer(
				InstancePtr->SpiInstPtr,
				InstancePtr->SpiInstPtr->Msg, ByteCount);
#elif defined(XPAR_XISF_INTERFACE_OSPIPSV)
		Status = InstancePtr->XIsf_Iface_Transfer(
			InstancePtr->SpiInstPtr, InstancePtr->SpiInstPtr->Msg);
#else
		Status = InstancePtr->XIsf_Iface_Transfer(
				InstancePtr->SpiInstPtr,
					WritePtr, ReadPtr, ByteCount);
#endif
#if defined(XPAR_XISF_INTERFACE_PSQSPI) || \
	defined(XPAR_XISF_INTERFACE_PSSPI) || \
	defined(XPAR_XISF_INTERFACE_QSPIPSU) || \
	defined(XPAR_XISF_INTERFACE_OSPIPSV)
		while (1) {
			if (XIsf_TransferInProgress == 0)
				break;
		}
#endif
	} else {
#if XPAR_XISF_INTERFACE_QSPIPSU
		Status = InstancePtr->XIsf_Iface_PolledTransfer(
				InstancePtr->SpiInstPtr,
				InstancePtr->SpiInstPtr->Msg, ByteCount);
#elif defined(XPAR_XISF_INTERFACE_OSPIPSV)
		Status = InstancePtr->XIsf_Iface_PolledTransfer(
			InstancePtr->SpiInstPtr, InstancePtr->SpiInstPtr->Msg);
#else
		Status = InstancePtr->XIsf_Iface_PolledTransfer(
				InstancePtr->SpiInstPtr,
					WritePtr, ReadPtr, ByteCount);
#endif
	}

	if (Status != (int)(XST_SUCCESS))
		return (int)(XST_FAILURE);

	return (int)(XST_SUCCESS);
}


/*****************************************************************************/
/**
 * @brief
 * This API registers the interface SPI/SPI PS/QSPI PS.
 *
 * @param	InstancePtr	Pointer to the XIsf instance.
 *
 * @return	None
 *
 *
 ******************************************************************************/
void XIsf_RegisterInterface(XIsf *InstancePtr)
{
#ifdef XPAR_XISF_INTERFACE_AXISPI
	InstancePtr->XIsf_Iface_SetOptions = XSpi_SetOptions;
	InstancePtr->XIsf_Iface_SetSlaveSelect = XSpi_SetSlaveSelect;
	InstancePtr->XIsf_Iface_Transfer = XSpi_Transfer;
	InstancePtr->XIsf_Iface_Start = XSpi_Start;
#elif XPAR_XISF_INTERFACE_PSSPI
	InstancePtr->XIsf_Iface_SetOptions = XSpiPs_SetOptions;
	InstancePtr->XIsf_Iface_SetSlaveSelect = XSpiPs_SetSlaveSelect;
	InstancePtr->XIsf_Iface_Transfer = XSpiPs_Transfer;
	InstancePtr->XIsf_Iface_PolledTransfer = XSpiPs_PolledTransfer;
	InstancePtr->XIsf_Iface_SetClkPrescaler = XSpiPs_SetClkPrescaler;
#elif XPAR_XISF_INTERFACE_QSPIPSU
	InstancePtr->XIsf_Iface_SetOptions = XQspiPsu_SetOptions;
	InstancePtr->XIsf_Iface_SetSlaveSelect = XQspiPsu_SelectFlash;
	InstancePtr->XIsf_Iface_Transfer = XQspiPsu_InterruptTransfer;
	InstancePtr->XIsf_Iface_PolledTransfer = XQspiPsu_PolledTransfer;
	InstancePtr->XIsf_Iface_SetClkPrescaler = XQspiPsu_SetClkPrescaler;
#elif XPAR_XISF_INTERFACE_PSQSPI
	InstancePtr->XIsf_Iface_SetOptions = XQspiPs_SetOptions;
	InstancePtr->XIsf_Iface_SetSlaveSelect = XQspiPs_SetSlaveSelect;
	InstancePtr->XIsf_Iface_Transfer = XQspiPs_Transfer;
	InstancePtr->XIsf_Iface_PolledTransfer = XQspiPs_PolledTransfer;
	InstancePtr->XIsf_Iface_SetClkPrescaler = XQspiPs_SetClkPrescaler;
#elif XPAR_XISF_INTERFACE_OSPIPSV
	InstancePtr->XIsf_Iface_SetOptions = XOspiPsv_SetOptions;
	InstancePtr->XIsf_Iface_SetSlaveSelect = XOspiPsv_SelectFlash;
	InstancePtr->XIsf_Iface_Transfer = XOspiPsv_IntrTransfer;
	InstancePtr->XIsf_Iface_PolledTransfer = XOspiPsv_PollTransfer;
	InstancePtr->XIsf_Iface_SetClkPrescaler = XOspiPsv_SetClkPrescaler;
#endif
}


#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
/*****************************************************************************/
/**
 *
 * This function initializes the instance structure with the device geometry of
 * the Atmel Serial Flash if it is an Atmel device.
 *
 * @param	InstancePtr is a pointer to the XIsf instance.
 * @param	BufferPtr is a pointer to the memory where the device info of
 *		the Serial Flash is present.
 *
 * @return	- XST_SUCCESS if device information matches the JEDEC
 *		information of the Atmel Serial Flash.
 *		- XST_FAILURE if device information doesn't match with Atmel
 *		Serial Flash.
 *
 * @note		None
 *
 ******************************************************************************/
static int AtmelFlashInitialize(XIsf *InstancePtr, u8 *BufferPtr)
{
	int Status = (int)(XST_FAILURE);
	u32 Index;
	u8 StatusRegister;
	u8 NumOfDevices;
	u8 ManufacturerID;

	ManufacturerID = BufferPtr[BYTE2];
	if (ManufacturerID == XISF_MANUFACTURER_ID_ATMEL) {

		/*
		 * For Atmel Serial Flash the device code is the 3rd byte of
		 * JEDEC info.
		 */
		InstancePtr->DeviceCode = BufferPtr[BYTE3];

		/*
		 * Get the Status Register contents.
		 * The IsReady is temporarily made TRUE to fetch the Status
		 * Register contents.
		 */
		InstancePtr->IsReady = TRUE;
		Status = XIsf_GetStatus(InstancePtr, BufferPtr);
		InstancePtr->IsReady = FALSE;
		if (Status != (int)(XST_SUCCESS))
			return (int)(XST_FAILURE);

		/*
		 * Wait until the transfer is complete.
		 */
		do {
#ifndef XPAR_XISF_INTERFACE_PSQSPI
			Status = InstancePtr->XIsf_Iface_SetSlaveSelect(
					InstancePtr->SpiInstPtr,
						InstancePtr->SpiSlaveSelect);
#else
			Status = InstancePtr->XIsf_Iface_SetSlaveSelect(
					InstancePtr->SpiInstPtr);
#endif
		} while (Status == XST_DEVICE_BUSY);

		if (Status != (int)(XST_SUCCESS))
			return (int)(XST_FAILURE);

		StatusRegister = BufferPtr[BYTE2];

		/*
		 * Get the Address mode from the Status Register of Serial
		 * Flash.
		 */
		InstancePtr->AddrMode = StatusRegister &
					XISF_SR_ADDR_MODE_MASK;

		/*
		 * Update the Serial Flash instance structure with device
		 * geometry.
		 */
		 NumOfDevices = sizeof(AtmelDevices) /
				sizeof(struct AtmelDeviceGeometry);

		for (Index = 0; Index < NumOfDevices; Index++) {
			if (InstancePtr->DeviceCode ==
					 AtmelDevices[Index].DeviceCode) {
				/*
				 * Default address mode device.
				 */
				if (InstancePtr->AddrMode ==
						 XISF_DEFAULT_ADDRESS) {
					InstancePtr->BytesPerPage =
				AtmelDevices[Index].BytesPerPageDefaultMode;
				} else {
					/*
					 * Power of 2 address mode device.
					 */
					InstancePtr->BytesPerPage =
				AtmelDevices[Index].BytesPerPagePowerOf2Mode;
				}

				InstancePtr->PagesPerBlock =
					AtmelDevices[Index].PagesPerBlock;

				InstancePtr->BlocksPerSector =
					AtmelDevices[Index].BlocksPerSector;

				InstancePtr->NumOfSectors =
					AtmelDevices[Index].NumOfSectors;

				if (InstancePtr->BytesPerPage >
						XISF_BYTES1024_PER_PAGE)
					InstancePtr->ByteMask =
						XISF_BYTES2048_PER_PAGE_MASK;
				else if (InstancePtr->BytesPerPage >
						XISF_BYTES512_PER_PAGE)
					InstancePtr->ByteMask =
						XISF_BYTES1024_PER_PAGE_MASK;
				else if (InstancePtr->BytesPerPage >
						XISF_BYTES256_PER_PAGE)
					InstancePtr->ByteMask =
						XISF_BYTES512_PER_PAGE_MASK;
				else
					InstancePtr->ByteMask =
						XISF_BYTES256_PER_PAGE_MASK;

				InstancePtr->IsReady = TRUE;
			}
		}
	}

	/*
	 * If the device is not supported, return Failure.
	 */
	if (InstancePtr->IsReady != TRUE)
		return (int)(XST_FAILURE);

	return (int)(XST_SUCCESS);
}
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */

#if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \
	(defined(XPAR_XISF_INTERFACE_AXISPI) || \
	defined(XPAR_XISF_INTERFACE_QSPIPSU) || \
	defined(XPAR_XISF_INTERFACE_OSPIPSV)))
/*****************************************************************************/
/**
 * @brief
 * This API enters the Micron flash device into 4 bytes addressing mode.
 * As per the Micron spec, before issuing the command to enter into 4 byte addr
 * mode, a write enable command is issued.
 *
 * @param	InstancePtr	Pointer to the XIsf instance.
 *
 * @return
 *		- XST_SUCCESS if successful.
 *		- XST_FAILURE if it fails.
 *
 * @note		Applicable only for Micron flash devices
 *
 ******************************************************************************/
int XIsf_MicronFlashEnter4BAddMode(XIsf *InstancePtr)
{
	int Status = (int)(XST_FAILURE);
	u8 *NULLPtr = NULL;
	u8 Mode;
#ifdef XPAR_XISF_INTERFACE_QSPIPSU
	u8 ReadStatusCmd, FSRFlag;
#endif
#if (defined(XPAR_XISF_INTERFACE_QSPIPSU) || \
		defined(XPAR_XISF_INTERFACE_OSPIPSV))
	u8 FlashStatus[2] __attribute__ ((aligned(4))) = {0};
#endif
	u8  FlashMake;

	if (InstancePtr == NULL)
		return (int)(XST_FAILURE);

	if (InstancePtr->IsReady != TRUE)
		return (int)(XST_FAILURE);

	if (InstancePtr->FourByteAddrMode == TRUE)
		return (int)(XST_SUCCESS);

	if (InstancePtr->ManufacturerID == XISF_MANUFACTURER_ID_MICRON ||
		InstancePtr->ManufacturerID == XISF_MANUFACTURER_ID_MACRONIX ||
		InstancePtr->ManufacturerID == XISF_MANUFACTURER_ID_ISSI ||
		InstancePtr->ManufacturerID == XISF_MANUFACTURER_ID_MICRON_OCTAL) {

#ifdef XPAR_XISF_INTERFACE_QSPIPSU
		FlashMake = (u32)InstancePtr->ManufacturerID;

		InstancePtr->WriteBufPtr[BYTE1] =
				XISF_CMD_ENTER_4BYTE_ADDR_MODE;
		/*
		 * Enable write before transfer
		 */
		Status = XIsf_WriteEnable(InstancePtr, XISF_WRITE_ENABLE);
		if (Status != (int)XST_SUCCESS)
			return (int)XST_FAILURE;

		FlashMsg[0].TxBfrPtr = InstancePtr->WriteBufPtr;
		FlashMsg[0].RxBfrPtr = NULL;
		FlashMsg[0].ByteCount = 1;
		FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
		FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
		InstancePtr->SpiInstPtr->Msg = FlashMsg;

		Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, 1);
		if (Status != (int)(XST_SUCCESS))
			return (int)(XST_FAILURE);

		if ((InstancePtr->NumDie > (u8)1) &&
			(FlashMake == (u32)XISF_MANUFACTURER_ID_MICRON)) {
			ReadStatusCmd = READ_FLAG_STATUS_CMD;
			FSRFlag = 1;
		} else {
			ReadStatusCmd = READ_STATUS_CMD;
			FSRFlag = 0;
		}

		while (1) {
			FlashMsg[0].TxBfrPtr = &ReadStatusCmd;
			FlashMsg[0].RxBfrPtr = NULL;
			FlashMsg[0].ByteCount = 1;
			FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
			FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;

			FlashMsg[1].TxBfrPtr = NULL;
			FlashMsg[1].RxBfrPtr = FlashStatus;
			FlashMsg[1].ByteCount = 2;
			FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
			FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX;

			if (InstancePtr->SpiInstPtr->Config.ConnectionMode ==
					XISF_QSPIPS_CONNECTION_MODE_PARALLEL) {
				FlashMsg[1].Flags |= XQSPIPSU_MSG_FLAG_STRIPE;
			}
			InstancePtr->SpiInstPtr->Msg = FlashMsg;

			Status = XIsf_Transfer(InstancePtr,
					NULLPtr, NULLPtr, 2);
			if (Status != XST_SUCCESS)
				return XST_FAILURE;

			if (InstancePtr->SpiInstPtr->Config.ConnectionMode ==
					XISF_QSPIPS_CONNECTION_MODE_PARALLEL){
				if (FSRFlag)
					FlashStatus[1] &= FlashStatus[0];
				else
					FlashStatus[1] |= FlashStatus[0];
			}

			if (FSRFlag) {
				if ((FlashStatus[1] & 0x80) != 0)
					break;
			} else {
				if ((FlashStatus[1] & 0x01) == 0)
					break;
			}
		}
#else
#ifdef XPAR_XISF_INTERFACE_OSPIPSV
		(void)FlashMake;
		/*
		 * Enable write before transfer
		 */
		Status = XIsf_WriteEnable(InstancePtr, XISF_WRITE_ENABLE);
		if (Status != (int)XST_SUCCESS)
			return (int)XST_FAILURE;

		FlashMsg.Opcode = XISF_CMD_ENTER_4BYTE_ADDR_MODE;
		FlashMsg.Addrvalid = 0;
		FlashMsg.Addrsize = 0;
		FlashMsg.TxBfrPtr = NULL;
		FlashMsg.RxBfrPtr = NULL;
		FlashMsg.ByteCount = 0;
		FlashMsg.Flags = XOSPIPSV_MSG_FLAG_TX;
		FlashMsg.IsDDROpCode = 0;
		FlashMsg.Proto = 0;
		if (InstancePtr->SpiInstPtr->SdrDdrMode == XOSPIPSV_EDGE_MODE_DDR_PHY) {
			FlashMsg.Proto = XOSPIPSV_WRITE_8_0_0;
		}
		InstancePtr->SpiInstPtr->Msg = &FlashMsg;
		Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, FlashMsg.ByteCount);
		if (Status != (int)XST_SUCCESS)
			return (int)XST_FAILURE;

		while (1) {
			FlashMsg.Opcode = READ_FLAG_STATUS_CMD;
			FlashMsg.Addrsize = 0;
			FlashMsg.Addrvalid = 0;
			FlashMsg.TxBfrPtr = NULL;
			FlashMsg.RxBfrPtr = FlashStatus;
			FlashMsg.ByteCount = 1;
			FlashMsg.Flags = XOSPIPSV_MSG_FLAG_RX;
			FlashMsg.Dummy = 0;
			FlashMsg.IsDDROpCode = 0;
			FlashMsg.Proto = 0;
			if (InstancePtr->SpiInstPtr->SdrDdrMode == XOSPIPSV_EDGE_MODE_DDR_PHY) {
				FlashMsg.Proto = XOSPIPSV_READ_8_0_8;
				FlashMsg.ByteCount = 2;
				FlashMsg.Dummy = 8;
			}
			InstancePtr->SpiInstPtr->Msg = &FlashMsg;
			Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, FlashMsg.ByteCount);
			if (Status != (int)XST_SUCCESS)
				return (int)XST_FAILURE;

			if ((FlashStatus[0] & 0x80) != 0)
				break;
		}

#else
		FlashMake = (u32)InstancePtr->ManufacturerID;

		InstancePtr->WriteBufPtr[BYTE1] =
				XISF_CMD_ENTER_4BYTE_ADDR_MODE;

		Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr,
				NULLPtr, XISF_CMD_4BYTE_ADDR_ENTER_EXIT_BYTES);
#endif
#endif

		Mode = XIsf_GetTransferMode(InstancePtr);

		if (Mode == XISF_INTERRUPT_MODE) {
#ifndef XPAR_XISF_INTERFACE_OSPIPSV
			InstancePtr->StatusHandler(InstancePtr,
					XIsf_StatusEventInfo, XIsf_ByteCountInfo);
#else
		InstancePtr->StatusHandler(InstancePtr, XIsf_StatusEventInfo);
#endif
		}

		if (Status != (int)(XST_SUCCESS))
			return (int)(XST_FAILURE);
	}

	InstancePtr->FourByteAddrMode = TRUE;
	return Status;
}

/*****************************************************************************/
/**
 * @brief
 * This API exits the Micron flash device from 4 bytes addressing mode.
 * As per the Micron spec, before issuing this command a write enable command
 * is first issued.
 *
 * @param	InstancePtr	Pointer to the XIsf instance.
 *
 * @return
 *		- XST_SUCCESS if successful.
 *		- XST_FAILURE if it fails.
 *
 * @note		Applicable only for Micron flash devices
 *
 ******************************************************************************/
int XIsf_MicronFlashExit4BAddMode(XIsf *InstancePtr)
{
	int Status = (int)(XST_FAILURE);
	u8 *NULLPtr = NULL;
	u8 Mode;
#ifdef XPAR_XISF_INTERFACE_QSPIPSU
	u8 ReadStatusCmd, FSRFlag;
#endif
#if (defined(XPAR_XISF_INTERFACE_QSPIPSU) || \
		defined(XPAR_XISF_INTERFACE_OSPIPSV))
	u8 FlashStatus[2] __attribute__ ((aligned(4))) = {0};
#endif
	u8 FlashMake;

	if (InstancePtr == NULL)
		return (int)(XST_FAILURE);

	if (InstancePtr->IsReady != TRUE)
		return (int)(XST_FAILURE);

	if (InstancePtr->FourByteAddrMode == FALSE)
		return (int)(XST_SUCCESS);

	if (InstancePtr->ManufacturerID == XISF_MANUFACTURER_ID_MICRON ||
		InstancePtr->ManufacturerID == XISF_MANUFACTURER_ID_MACRONIX ||
		InstancePtr->ManufacturerID == XISF_MANUFACTURER_ID_ISSI ||
		InstancePtr->ManufacturerID == XISF_MANUFACTURER_ID_MICRON_OCTAL) {

#ifdef XPAR_XISF_INTERFACE_QSPIPSU
		FlashMake = (u32)InstancePtr->ManufacturerID;

		if (InstancePtr->ManufacturerID == XISF_MANUFACTURER_ID_ISSI) {
			InstancePtr->WriteBufPtr[BYTE1] =
					XISF_CMD_EXIT_4BYTE_ADDR_MODE_ISSI;
		} else {
			InstancePtr->WriteBufPtr[BYTE1] =
					XISF_CMD_EXIT_4BYTE_ADDR_MODE;
		}
		/*
		 * Enable write before transfer
		 */
		Status = XIsf_WriteEnable(InstancePtr, XISF_WRITE_ENABLE);
		if (Status != (int)XST_SUCCESS)
			return (int)XST_FAILURE;

		FlashMsg[0].TxBfrPtr = InstancePtr->WriteBufPtr;
		FlashMsg[0].RxBfrPtr = NULL;
		FlashMsg[0].ByteCount = 1;
		FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
		FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
		InstancePtr->SpiInstPtr->Msg = FlashMsg;

		Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, 1);
		if (Status != (int)(XST_SUCCESS))
			return (int)(XST_FAILURE);

		if ((InstancePtr->NumDie > (u8)1) &&
			(FlashMake == (u32)XISF_MANUFACTURER_ID_MICRON)) {
			ReadStatusCmd = READ_FLAG_STATUS_CMD;
			FSRFlag = 1;
		} else {
			ReadStatusCmd = READ_STATUS_CMD;
			FSRFlag = 0;
		}

		while (1) {
			FlashMsg[0].TxBfrPtr = &ReadStatusCmd;
			FlashMsg[0].RxBfrPtr = NULL;
			FlashMsg[0].ByteCount = 1;
			FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
			FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;

			FlashMsg[1].TxBfrPtr = NULL;
			FlashMsg[1].RxBfrPtr = FlashStatus;
			FlashMsg[1].ByteCount = 2;
			FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
			FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX;

			if (InstancePtr->SpiInstPtr->Config.ConnectionMode ==
					XISF_QSPIPS_CONNECTION_MODE_PARALLEL)
				FlashMsg[1].Flags |= XQSPIPSU_MSG_FLAG_STRIPE;

			InstancePtr->SpiInstPtr->Msg = FlashMsg;

			Status = XIsf_Transfer(InstancePtr,
					NULLPtr, NULLPtr, 2);
			if (Status != XST_SUCCESS)
				return XST_FAILURE;

			if (InstancePtr->SpiInstPtr->Config.ConnectionMode ==
					XISF_QSPIPS_CONNECTION_MODE_PARALLEL) {
				if (FSRFlag)
					FlashStatus[1] &= FlashStatus[0];
				else
					FlashStatus[1] |= FlashStatus[0];
			}

			if (FSRFlag) {
				if ((FlashStatus[1] & 0x80) != 0)
					break;
			} else {
				if ((FlashStatus[1] & 0x01) == 0)
					break;
			}
		}
#else
#ifdef XPAR_XISF_INTERFACE_OSPIPSV
		(void)FlashMake;
		/*
		 * Enable write before transfer
		 */
		Status = XIsf_WriteEnable(InstancePtr, XISF_WRITE_ENABLE);
		if (Status != (int)XST_SUCCESS)
			return (int)XST_FAILURE;

		FlashMsg.Opcode = XISF_CMD_EXIT_4BYTE_ADDR_MODE;
		FlashMsg.Addrvalid = 0;
		FlashMsg.Addrsize = 0;
		FlashMsg.TxBfrPtr = NULL;
		FlashMsg.RxBfrPtr = NULL;
		FlashMsg.ByteCount = 0;
		FlashMsg.Flags = XOSPIPSV_MSG_FLAG_TX;
		FlashMsg.Addrsize = 3;
		FlashMsg.IsDDROpCode = 0;
		FlashMsg.Proto = 0;
		if (InstancePtr->SpiInstPtr->SdrDdrMode == XOSPIPSV_EDGE_MODE_DDR_PHY) {
			FlashMsg.Proto = XOSPIPSV_WRITE_8_0_0;
		}
		InstancePtr->SpiInstPtr->Msg = &FlashMsg;
		Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, FlashMsg.ByteCount);
		if (Status != (int)XST_SUCCESS)
			return (int)XST_FAILURE;

		while (1) {
			FlashMsg.Opcode = READ_FLAG_STATUS_CMD;
			FlashMsg.Addrsize = 0;
			FlashMsg.Addrvalid = 0;
			FlashMsg.TxBfrPtr = NULL;
			FlashMsg.RxBfrPtr = FlashStatus;
			FlashMsg.ByteCount = 1;
			FlashMsg.Flags = XOSPIPSV_MSG_FLAG_RX;
			FlashMsg.Dummy = 0;
			FlashMsg.IsDDROpCode = 0;
			FlashMsg.Proto = 0;
			if (InstancePtr->SpiInstPtr->SdrDdrMode == XOSPIPSV_EDGE_MODE_DDR_PHY) {
				FlashMsg.Proto = XOSPIPSV_READ_8_0_8;
				FlashMsg.ByteCount = 2;
				FlashMsg.Dummy = 8;
			}
			InstancePtr->SpiInstPtr->Msg = &FlashMsg;
			Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, FlashMsg.ByteCount);
			if (Status != (int)XST_SUCCESS)
				return (int)XST_FAILURE;

			if ((FlashStatus[0] & 0x80) != 0)
				break;
		}

#else
		FlashMake = (u32)InstancePtr->ManufacturerID;

		if (InstancePtr->ManufacturerID == XISF_MANUFACTURER_ID_ISSI) {
			InstancePtr->WriteBufPtr[BYTE1] =
					XISF_CMD_EXIT_4BYTE_ADDR_MODE_ISSI;
		} else {
			InstancePtr->WriteBufPtr[BYTE1] =
					XISF_CMD_EXIT_4BYTE_ADDR_MODE;
		}
		Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr,
				NULLPtr, XISF_CMD_4BYTE_ADDR_ENTER_EXIT_BYTES);
#endif
#endif

		Mode = XIsf_GetTransferMode(InstancePtr);

		if (Mode == XISF_INTERRUPT_MODE) {
#ifndef XPAR_XISF_INTERFACE_OSPIPSV
			InstancePtr->StatusHandler(InstancePtr,
					XIsf_StatusEventInfo, XIsf_ByteCountInfo);
#else
		InstancePtr->StatusHandler(InstancePtr, XIsf_StatusEventInfo);
#endif
		}

		if (Status != (int)(XST_SUCCESS))
			return (int)(XST_FAILURE);
	}
	InstancePtr->FourByteAddrMode = FALSE;
	return Status;
}
#endif
/*
 * ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \
 * (defined(XPAR_XISF_INTERFACE_AXISPI) || \
 * defined (XPAR_XISF_INTERFACE_QSPIPSU)|| \
 * defined(XPAR_XISF_INTERFACE_OSPIPSV)))
 */

#if (((XPAR_XISF_FLASH_FAMILY == INTEL) || \
	(XPAR_XISF_FLASH_FAMILY == STM) || \
	(XPAR_XISF_FLASH_FAMILY == SST) || \
	(XPAR_XISF_FLASH_FAMILY == WINBOND) || \
	(XPAR_XISF_FLASH_FAMILY == SPANSION)) && \
	(!defined(XPAR_XISF_INTERFACE_PSQSPI)) && \
	(!defined(XPAR_XISF_INTERFACE_QSPIPSU)) && \
	(!defined(XPAR_XISF_INTERFACE_OSPIPSV)))
/*****************************************************************************/
/**
 *
 * This function initializes the instance structure with the device geometry of
 * the Intel/Stm/Winbond Serial Flash if it is an Intel/Stm/Winbond device.
 *
 * @param	InstancePtr is a pointer to the XIsf instance.
 * @param	BufferPtr is a pointer to the memory where the device info of
 *		the Serial Flash is present.
 *
 * @return	- XST_SUCCESS if device information matches the JEDEC
 *		information of Intel or Stm or Winbond Serial Flash.
 *		- XST_FAILURE if device information doesn't match with Intel
 *		or Stm or Winbond Serial Flash.
 *
 * @note		None
 *
 ******************************************************************************/
static int IntelStmFlashInitialize(XIsf *InstancePtr, u8 *BufferPtr)
{
	u32 Index;
	u8 NumOfDevices;
	u8 ManufacturerID;
#if (XPAR_XISF_FLASH_FAMILY == SST)
	int Status = (int)(XST_FAILURE);
	u8 *NULLPtr = NULL;
	u8 UnlkBlkProt[1] = { GLOBAL_BLK_PROT_UNLK };
#endif

	ManufacturerID = BufferPtr[BYTE2];

#if (XPAR_XISF_FLASH_FAMILY == INTEL)
	/*
	 * For Intel the device code is the 4th byte of the JEDEC info.
	 */
	InstancePtr->DeviceCode = BufferPtr[BYTE4];
#else
	/*
	 * For STM/Winbond/Spansion Serial Flash the device code is 3rd/4th
	 * byte of the JEDEC info. The Third Byte is Memory Type and the 4th
	 * byte represents the capacity.
	 */
	InstancePtr->DeviceCode = (BufferPtr[BYTE3] << 8) | BufferPtr[BYTE4];
#endif

	/*
	 * Check for Intel/STM/Winbond/Spansion Serial Flash.
	 */
	NumOfDevices = sizeof(IntelStmDevices) /
			sizeof(struct IntelStmDeviceGeometry);

	for (Index = 0; Index < NumOfDevices; Index++) {
		if ((InstancePtr->DeviceCode ==
				IntelStmDevices[Index].DeviceCode) &&
				(ManufacturerID ==
				IntelStmDevices[Index].ManufacturerID)) {
			InstancePtr->ManufacturerID =
					IntelStmDevices[Index].ManufacturerID;
			InstancePtr->BytesPerPage =
				IntelStmDevices[Index].BytesPerPage;

			/*
			 * This is number of pages per Sector.
			 */
			InstancePtr->PagesPerBlock =
				IntelStmDevices[Index].PagesPerSector;

			InstancePtr->BlocksPerSector = 0;

			InstancePtr->NumOfSectors =
				IntelStmDevices[Index].NumOfSectors;

			InstancePtr->IsReady = TRUE;
#if (XPAR_XISF_FLASH_FAMILY == SST)
			Status = XIsf_WriteEnable(InstancePtr, XISF_WRITE_ENABLE);
			if (Status != (int)XST_SUCCESS)
				return (int)XST_FAILURE;

			Status = XIsf_Transfer(InstancePtr, UnlkBlkProt, NULLPtr,
							sizeof(UnlkBlkProt));
			if (Status != (int)XST_SUCCESS)
				return (int)XST_FAILURE;
#endif
		}
	}

	/*
	 * If the device is not supported, return Failure.
	 */
	if (InstancePtr->IsReady != TRUE)
		return (int)(XST_FAILURE);

	return (int)(XST_SUCCESS);
}
#endif
/*
 * (((XPAR_XISF_FLASH_FAMILY==INTEL) || \
 * (XPAR_XISF_FLASH_FAMILY==STM) || \
 * (XPAR_XISF_FLASH_FAMILY == SST) || \
 * (XPAR_XISF_FLASH_FAMILY == WINBOND) || \
 * (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \
 * (!defined(XPAR_XISF_INTERFACE_PSQSPI)) && \
 * (!defined(XPAR_XISF_INTERFACE_QSPIPSU)) && \
 * (!defined(XPAR_XISF_INTERFACE_OSPIPSV)))
 */

#if  (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \
	(XPAR_XISF_FLASH_FAMILY == SPANSION)) && \
	(defined(XPAR_XISF_INTERFACE_PSQSPI) || \
	defined(XPAR_XISF_INTERFACE_QSPIPSU) || \
	defined(XPAR_XISF_INTERFACE_OSPIPSV)))
/*****************************************************************************/
/**
 *
 * This function initializes the instance structure with the device geometry of
 * the Spansion/Micron/Winbond Serial Flash if it is an Spansion/Micron/Winbond
 * device.
 *
 * @param	InstancePtr is a pointer to the XIsf instance.
 * @param	BufferPtr is a pointer to the memory where the device info of
 *		the Serial Flash is present.
 *
 * @return	- XST_SUCCESS if device information matches the JEDEC
 *		  information of Intel or Stm or Winbond Serial Flash.
 *		- XST_FAILURE if the device information doesn't match with
 *		  Intel or Stm or Winbond Serial Flash.
 *
 * @note		None
 *
 ******************************************************************************/
static int SpaMicWinFlashInitialize(XIsf *InstancePtr, u8 *BufferPtr)
{
	unsigned int StartIndex;
	u32 FlashMake;
#ifndef XPAR_XISF_INTERFACE_OSPIPSV
	u8 *WriteBfrPtr = InstancePtr->WriteBufPtr;
#endif
	int Status = (int)(XST_FAILURE);

#if (defined(XPAR_XISF_INTERFACE_QSPIPSU) ||\
		defined(XPAR_XISF_INTERFACE_OSPIPSV))
	u8 *NULLPtr = NULL;
#endif

#ifdef XPAR_XISF_INTERFACE_QSPIPSU
	/*
	 * Read ID
	 */
	*WriteBfrPtr = READ_ID;
	FlashMsg[0].TxBfrPtr = WriteBfrPtr;
	FlashMsg[0].RxBfrPtr = NULL;
	FlashMsg[0].ByteCount = 1;
	FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
	FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;

	FlashMsg[1].TxBfrPtr = NULL;
	FlashMsg[1].RxBfrPtr = BufferPtr;
	FlashMsg[1].ByteCount = 3;
	FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
	FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX;
	InstancePtr->SpiInstPtr->Msg = FlashMsg;

	Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, 2);

	BufferPtr[1] = BufferPtr[0];
	BufferPtr[3] = BufferPtr[2];
#else
#ifdef XPAR_XISF_INTERFACE_OSPIPSV
	FlashMsg.Opcode = XISF_CMD_ISFINFO_READ;
	FlashMsg.Addrsize = 0;
	FlashMsg.Addrvalid = 0;
	FlashMsg.TxBfrPtr = NULL;
	FlashMsg.RxBfrPtr = BufferPtr;
	FlashMsg.ByteCount = 6;
	FlashMsg.Flags = XOSPIPSV_MSG_FLAG_RX;
	FlashMsg.Dummy = 0;
	FlashMsg.IsDDROpCode = 0;
	if (InstancePtr->SpiInstPtr->SdrDdrMode == XOSPIPSV_EDGE_MODE_DDR_PHY) {
		FlashMsg.Dummy = 8;
		FlashMsg.Proto = XOSPIPSV_READ_8_0_8;
	}
	InstancePtr->SpiInstPtr->Msg = &FlashMsg;
	/*
	 * Initiate the Transfer.
	 */
	Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, XISF_INFO_READ_BYTES);
#else
	/*
	 * Read ID in Auto mode.
	 */
	WriteBfrPtr[BYTE1] = READ_ID;
	WriteBfrPtr[BYTE2] = 0x23U;		/* 3 dummy bytes */
	WriteBfrPtr[BYTE3] = 0x08U;
	WriteBfrPtr[BYTE4] = 0x09U;

	Status = XIsf_Transfer(InstancePtr, WriteBfrPtr, BufferPtr,
				RD_ID_SIZE);
#endif
#endif
	if (Status != (int)(XST_SUCCESS))
		return (int)(XST_FAILURE);

#ifdef XPAR_XISF_INTERFACE_OSPIPSV
	if (BufferPtr[0] == XISF_MANUFACTURER_ID_MICRON_OCTAL) {
		FlashMake = XISF_MANUFACTURER_ID_MICRON_OCTAL;
		StartIndex = 0;
		XIsf_FCTIndex = StartIndex;
	}
#else
	/*
	 * Deduce flash make
	 */
	if (BufferPtr[1] == XISF_MANUFACTURER_ID_MICRON) {
		FlashMake = XISF_MANUFACTURER_ID_MICRON;
		StartIndex = MICRON_INDEX_START;
	} else if (BufferPtr[1] == XISF_MANUFACTURER_ID_SPANSION) {
		FlashMake = XISF_MANUFACTURER_ID_SPANSION;
		StartIndex = SPANSION_INDEX_START;
	} else if (BufferPtr[1] == XISF_MANUFACTURER_ID_WINBOND) {
		FlashMake = XISF_MANUFACTURER_ID_WINBOND;
		StartIndex = WINBOND_INDEX_START;
	} else if (BufferPtr[1] == XISF_MANUFACTURER_ID_ISSI) {
		FlashMake = XISF_MANUFACTURER_ID_ISSI;
		StartIndex = ISSI_INDEX_START;
	} else if (BufferPtr[1] == XISF_MANUFACTURER_ID_MACRONIX) {
		FlashMake = XISF_MANUFACTURER_ID_MACRONIX;
		StartIndex = MACRONIX_INDEX_START;
	} else {
		FlashMake = 0;
		StartIndex = 0;
	}
	/*
	 * If valid flash ID, then check connection mode & size and
	 * assign corresponding index in the Flash configuration table
	 */
	if (((FlashMake == XISF_MANUFACTURER_ID_MICRON) ||
		(FlashMake == XISF_MANUFACTURER_ID_SPANSION) ||
		(FlashMake == XISF_MANUFACTURER_ID_WINBOND)) &&
		(BufferPtr[3] == XISF_MICRON_ID_BYTE2_128)) {
		switch (InstancePtr->SpiInstPtr->Config.ConnectionMode) {
		case XISF_QSPIPS_CONNECTION_MODE_SINGLE:
			XIsf_FCTIndex =
				(u32)FLASH_CFG_TBL_SINGLE_128_SP +
					(u32)StartIndex;
			break;
		case XISF_QSPIPS_CONNECTION_MODE_PARALLEL:
			XIsf_FCTIndex =
				(u32)FLASH_CFG_TBL_PARALLEL_128_SP +
					(u32)StartIndex;
			break;
		case XISF_QSPIPS_CONNECTION_MODE_STACKED:
			XIsf_FCTIndex =
				(u32)FLASH_CFG_TBL_STACKED_128_SP +
					(u32)StartIndex;
			break;
		default:
			XIsf_FCTIndex = 0;
			break;
		}
	}

	/*
	 * 256 and 512Mbit supported only for Micron and Spansion,
	 * not Winbond
	 */
	if (((FlashMake == XISF_MANUFACTURER_ID_MICRON) ||
		(FlashMake == XISF_MANUFACTURER_ID_SPANSION)) &&
		(BufferPtr[3] == XISF_MICRON_ID_BYTE2_256)) {
		switch (InstancePtr->SpiInstPtr->Config.ConnectionMode) {
		case XISF_QSPIPS_CONNECTION_MODE_SINGLE:
			XIsf_FCTIndex = FLASH_CFG_TBL_SINGLE_256_SP +
					StartIndex;
			break;
		case XISF_QSPIPS_CONNECTION_MODE_PARALLEL:
			XIsf_FCTIndex = FLASH_CFG_TBL_PARALLEL_256_SP +
					StartIndex;
			break;
		case XISF_QSPIPS_CONNECTION_MODE_STACKED:
			XIsf_FCTIndex = FLASH_CFG_TBL_STACKED_256_SP +
					StartIndex;
			break;
		default:
			XIsf_FCTIndex = 0;
			break;
		}
	}

	/*
	 * For ISSI flash.
	 */
	if (FlashMake == XISF_MANUFACTURER_ID_ISSI) {
		if (BufferPtr[3] == XISF_ISSI_ID_BYTE2_08) {
			switch (InstancePtr->SpiInstPtr->Config.ConnectionMode) {
			case XISF_QSPIPS_CONNECTION_MODE_SINGLE:
				XIsf_FCTIndex = FLASH_CFG_TBL_SINGLE_08_ISSI;
				break;
			case XISF_QSPIPS_CONNECTION_MODE_PARALLEL:
				XIsf_FCTIndex = FLASH_CFG_TBL_PARALLEL_08_ISSI;
				break;
			case XISF_QSPIPS_CONNECTION_MODE_STACKED:
				XIsf_FCTIndex = FLASH_CFG_TBL_STACKED_08_ISSI;
				break;
			default:
				XIsf_FCTIndex = 0;
				break;
			}
		} else if (BufferPtr[3] == XISF_ISSI_ID_BYTE2_16) {
			switch (InstancePtr->SpiInstPtr->Config.ConnectionMode) {
			case XISF_QSPIPS_CONNECTION_MODE_SINGLE:
				XIsf_FCTIndex = FLASH_CFG_TBL_SINGLE_16_ISSI;
				break;
			case XISF_QSPIPS_CONNECTION_MODE_PARALLEL:
				XIsf_FCTIndex = FLASH_CFG_TBL_PARALLEL_16_ISSI;
				break;
			case XISF_QSPIPS_CONNECTION_MODE_STACKED:
				XIsf_FCTIndex = FLASH_CFG_TBL_STACKED_16_ISSI;
				break;
			default:
				XIsf_FCTIndex = 0;
				break;
			}
		} else if (BufferPtr[3] == XISF_ISSI_ID_BYTE2_32) {
			switch (InstancePtr->SpiInstPtr->Config.ConnectionMode) {
			case XISF_QSPIPS_CONNECTION_MODE_SINGLE:
				XIsf_FCTIndex = FLASH_CFG_TBL_SINGLE_32_ISSI;
				break;
			case XISF_QSPIPS_CONNECTION_MODE_PARALLEL:
				XIsf_FCTIndex = FLASH_CFG_TBL_PARALLEL_32_ISSI;
				break;
			case XISF_QSPIPS_CONNECTION_MODE_STACKED:
				XIsf_FCTIndex = FLASH_CFG_TBL_STACKED_32_ISSI;
				break;
			default:
				XIsf_FCTIndex = 0;
				break;
			}
		} else if (BufferPtr[3] == XISF_ISSI_ID_BYTE2_64) {
			switch (InstancePtr->SpiInstPtr->Config.ConnectionMode) {
			case XISF_QSPIPS_CONNECTION_MODE_SINGLE:
				XIsf_FCTIndex = FLASH_CFG_TBL_SINGLE_64_ISSI;
				break;
			case XISF_QSPIPS_CONNECTION_MODE_PARALLEL:
				XIsf_FCTIndex = FLASH_CFG_TBL_PARALLEL_64_ISSI;
				break;
			case XISF_QSPIPS_CONNECTION_MODE_STACKED:
				XIsf_FCTIndex = FLASH_CFG_TBL_STACKED_64_ISSI;
				break;
			default:
				XIsf_FCTIndex = 0;
				break;
			}
		} else if (BufferPtr[3] == XISF_ISSI_ID_BYTE2_128) {
                        switch (InstancePtr->SpiInstPtr->Config.ConnectionMode) {
                        case XISF_QSPIPS_CONNECTION_MODE_SINGLE:
                                XIsf_FCTIndex = FLASH_CFG_TBL_SINGLE_128_ISSI;
                                break;
                        case XISF_QSPIPS_CONNECTION_MODE_PARALLEL:
                                XIsf_FCTIndex = FLASH_CFG_TBL_PARALLEL_128_ISSI;
                                break;
                        case XISF_QSPIPS_CONNECTION_MODE_STACKED:
                                XIsf_FCTIndex = FLASH_CFG_TBL_STACKED_128_ISSI;
                                break;
                        default:
                                XIsf_FCTIndex = 0;
                                break;
                        }
                } else if (BufferPtr[3] == XISF_ISSI_ID_BYTE2_256) {
			switch (InstancePtr->SpiInstPtr->Config.ConnectionMode) {
			case XISF_QSPIPS_CONNECTION_MODE_SINGLE:
				XIsf_FCTIndex = FLASH_CFG_TBL_SINGLE_256_ISSI;
				break;
			case XISF_QSPIPS_CONNECTION_MODE_PARALLEL:
				XIsf_FCTIndex = FLASH_CFG_TBL_PARALLEL_256_ISSI;
				break;
			case XISF_QSPIPS_CONNECTION_MODE_STACKED:
				XIsf_FCTIndex = FLASH_CFG_TBL_STACKED_256_ISSI;
				break;
			default:
				XIsf_FCTIndex = 0;
				break;
			}
		} else if (BufferPtr[3] == XISF_ISSI_ID_BYTE2_512) {
                        switch (InstancePtr->SpiInstPtr->Config.ConnectionMode) {
                        case XISF_QSPIPS_CONNECTION_MODE_SINGLE:
                                XIsf_FCTIndex = FLASH_CFG_TBL_SINGLE_512_ISSI;
                                break;
                        case XISF_QSPIPS_CONNECTION_MODE_PARALLEL:
                                XIsf_FCTIndex = FLASH_CFG_TBL_PARALLEL_512_ISSI;
                                break;
                        case XISF_QSPIPS_CONNECTION_MODE_STACKED:
                                XIsf_FCTIndex = FLASH_CFG_TBL_STACKED_512_ISSI;
                                break;
                        default:
                                XIsf_FCTIndex = 0;
                                break;
                        }
                } else {
			XIsf_FCTIndex = 0;
		}
	}

	if (((FlashMake == XISF_MANUFACTURER_ID_MICRON) ||
		(FlashMake == XISF_MANUFACTURER_ID_SPANSION)) &&
		(BufferPtr[3] == XISF_MICRON_ID_BYTE2_512)) {
		switch (InstancePtr->SpiInstPtr->Config.ConnectionMode) {
		case XISF_QSPIPS_CONNECTION_MODE_SINGLE:
			XIsf_FCTIndex = FLASH_CFG_TBL_SINGLE_512_SP +
					StartIndex;
			break;
		case XISF_QSPIPS_CONNECTION_MODE_PARALLEL:
			XIsf_FCTIndex = FLASH_CFG_TBL_PARALLEL_512_SP +
					StartIndex;
			break;
		case XISF_QSPIPS_CONNECTION_MODE_STACKED:
			XIsf_FCTIndex = FLASH_CFG_TBL_STACKED_512_SP +
					StartIndex;
			break;
		default:
			XIsf_FCTIndex = 0;
			break;
		}
	}

	/*
	 * 1Gbit Single connection supported for Spansion.
	 * The ConnectionMode will indicate stacked as this part has 2 SS
	 * The device ID will indicate 512Mbit.
	 * This configuration is handled as the above 512Mbit stacked
	 * configuration.
	 */
	/* 1Gbit single, parallel and stacked supported for Micron */
	if ((FlashMake == XISF_MANUFACTURER_ID_MICRON) &&
		(BufferPtr[3] == XISF_MICRON_ID_BYTE2_1G)) {
		switch (InstancePtr->SpiInstPtr->Config.ConnectionMode) {
		case XISF_QSPIPS_CONNECTION_MODE_SINGLE:
			XIsf_FCTIndex = FLASH_CFG_TBL_SINGLE_1GB_MC;
			break;
		case XISF_QSPIPS_CONNECTION_MODE_PARALLEL:
			XIsf_FCTIndex = FLASH_CFG_TBL_PARALLEL_1GB_MC;
			break;
		case XISF_QSPIPS_CONNECTION_MODE_STACKED:
			XIsf_FCTIndex = FLASH_CFG_TBL_STACKED_1GB_MC;
			break;
		default:
			XIsf_FCTIndex = 0;
			break;
		}
	}

	/* 1Gbit single, parallel and stacked supported for Macronix */
	if (((FlashMake == XISF_MANUFACTURER_ID_MACRONIX) &&
		 ((BufferPtr[3] == XISF_MACRONIX_ID_BYTE2_1G) ||
		 (BufferPtr[3] == XISF_MACRONIX_ID_BYTE2_1GU)))) {

		switch (InstancePtr->SpiInstPtr->Config.ConnectionMode) {
		case XISF_QSPIPS_CONNECTION_MODE_SINGLE:
			if (BufferPtr[3] == XISF_MACRONIX_ID_BYTE2_1GU)
				XIsf_FCTIndex = FLASH_CFG_TBL_SINGLE_1GU_MX;
			else
				XIsf_FCTIndex = FLASH_CFG_TBL_SINGLE_1G_MX;
			break;
		case XISF_QSPIPS_CONNECTION_MODE_PARALLEL:
			if (BufferPtr[3] == XISF_MACRONIX_ID_BYTE2_1GU)
				XIsf_FCTIndex = FLASH_CFG_TBL_PARALLEL_1GU_MX;
			else
				XIsf_FCTIndex = FLASH_CFG_TBL_PARALLEL_1G_MX;
			break;
		case XISF_QSPIPS_CONNECTION_MODE_STACKED:
			if (BufferPtr[3] == XISF_MACRONIX_ID_BYTE2_1GU)
				XIsf_FCTIndex = FLASH_CFG_TBL_STACKED_1GU_MX;
			else
				XIsf_FCTIndex = FLASH_CFG_TBL_STACKED_1G_MX;
			break;
		default:
			XIsf_FCTIndex = 0;
			break;
		}
	}
#endif

	/*
	 * Populate the InstancePtr members with the appropriate values
	 * based on the XIsf_FCTIndex
	 */
	InstancePtr->BytesPerPage =
		(u16)(SpaMicWinDevices[XIsf_FCTIndex].PageSize);
	InstancePtr->NumDie = SpaMicWinDevices[XIsf_FCTIndex].NumDie;
	InstancePtr->DeviceIDMemSize =
			SpaMicWinDevices[XIsf_FCTIndex].DeviceIDMemSize;
	InstancePtr->ManufacturerID = FlashMake;
	InstancePtr->SectorSize = SpaMicWinDevices[XIsf_FCTIndex].SectSize;
	InstancePtr->NumSectors = SpaMicWinDevices[XIsf_FCTIndex].NumSect;
	InstancePtr->IsReady = TRUE;

#if (XPAR_XISF_FLASH_FAMILY == SPANSION) && \
		defined(XPAR_XISF_INTERFACE_OSPIPSV)
	Status = XIsf_MicronFlashEnter4BAddMode(InstancePtr);
	if (Status != (int)(XST_SUCCESS))
		return (int)(XST_FAILURE);
#endif

#if (XPAR_XISF_FLASH_FAMILY == SPANSION) && \
	defined(XPAR_XISF_INTERFACE_QSPIPSU)
	/*
	 * This will put the flash in 4Byte Addressing mode. Exit from
	 * 4Byte has to take care by the user if required.
	 */
	if (SpaMicWinDevices[XIsf_FCTIndex].FlashDeviceSize > SIXTEENMB) {
		if (InstancePtr->SpiInstPtr->Config.ConnectionMode ==
				XISF_QSPIPS_CONNECTION_MODE_PARALLEL) {
			InstancePtr->XIsf_Iface_SetSlaveSelect(
					InstancePtr->SpiInstPtr,
					XQSPIPSU_SELECT_FLASH_CS_BOTH,
					XQSPIPSU_SELECT_FLASH_BUS_BOTH);
			Status = XIsf_MicronFlashEnter4BAddMode(InstancePtr);
		} else {
			InstancePtr->XIsf_Iface_SetSlaveSelect(
					InstancePtr->SpiInstPtr,
						XQSPIPSU_SELECT_FLASH_CS_LOWER,
						XQSPIPSU_SELECT_FLASH_BUS_LOWER);
			Status = XIsf_MicronFlashEnter4BAddMode(InstancePtr);
			if (InstancePtr->SpiInstPtr->Config.ConnectionMode ==
					XISF_QSPIPS_CONNECTION_MODE_STACKED) {
				InstancePtr->XIsf_Iface_SetSlaveSelect(
						InstancePtr->SpiInstPtr,
						XQSPIPSU_SELECT_FLASH_CS_UPPER,
						XQSPIPSU_SELECT_FLASH_BUS_LOWER);
				Status = XIsf_MicronFlashEnter4BAddMode(InstancePtr);
			}
		}
		if (Status != (int)(XST_SUCCESS))
			return (int)(XST_FAILURE);
	}
#endif

	return (int)(XST_SUCCESS);
}
#endif
/**
 * (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \
 * (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \
 * (defined(XPAR_XISF_INTERFACE_PSQSPI) || \
 * defined (XPAR_XISF_INTERFACE_QSPIPSU) || \
 * defined(XPAR_XISF_INTERFACE_OSPIPSV)))
 */

#ifndef XPAR_XISF_INTERFACE_OSPIPSV
/*****************************************************************************/
/**
 * This functions translates the address based on the type of interconnection.
 * In case of stacked, this function asserts the corresponding slave select.
 *
 * @param	QspiPtr is a pointer to XIsf_Iface instance to be worked on.
 * @param	Address which is to be accessed (for erase, write or read)
 *
 * @return	RealAddr is the translated address - for single it is unchanged
 *       for stacked, the lower flash size is subtracted
 *       for parallel the address is divided by 2.
 *
 * @note		None.
 *
 ******************************************************************************/
u32 GetRealAddr(XIsf_Iface *QspiPtr, u32 Address)
{
#if (!defined(XPAR_XISF_INTERFACE_QSPIPSU)) && \
		(!defined(XPAR_XISF_INTERFACE_PSSPI))
	u32 LqspiCr;
#endif

#if	(defined(XPAR_XISF_INTERFACE_PSSPI))
	(void)QspiPtr;
#endif
	u32 RealAddr = {0};
#if defined(XPAR_XISF_INTERFACE_PSQSPI) || \
	defined(XPAR_XISF_INTERFACE_QSPIPSU)
	switch (QspiPtr->Config.ConnectionMode) {
	case XISF_QSPIPS_CONNECTION_MODE_SINGLE:
#ifdef XPAR_XISF_INTERFACE_QSPIPSU
		XQspiPsu_SelectFlash(QspiPtr, XQSPIPSU_SELECT_FLASH_CS_LOWER,
					XQSPIPSU_SELECT_FLASH_BUS_LOWER);
#endif
		RealAddr = Address;
		break;
	case XISF_QSPIPS_CONNECTION_MODE_STACKED:
#ifndef XPAR_XISF_INTERFACE_QSPIPSU
		/*
		 * Get the current LQSPI Config reg value
		 */
		LqspiCr = XQspiPs_GetLqspiConfigReg(QspiPtr);
#endif
		/* Select lower or upper Flash based on sector address */
		if (Address &
			SpaMicWinDevices[XIsf_FCTIndex].FlashDeviceSize) {
#ifdef XPAR_XISF_INTERFACE_QSPIPSU
			XQspiPsu_SelectFlash(QspiPtr,
				XQSPIPSU_SELECT_FLASH_CS_UPPER,
				XQSPIPSU_SELECT_FLASH_BUS_LOWER);
#else
			/*
			 * Set selection to U_PAGE
			 */
			XQspiPs_SetLqspiConfigReg(QspiPtr,
				LqspiCr | XQSPIPS_LQSPI_CR_U_PAGE_MASK);
#endif
			/*
			 * Subtract first flash size when accessing second
			 * flash.
			 */
			RealAddr = Address &
			(~SpaMicWinDevices[XIsf_FCTIndex].FlashDeviceSize);

		} else {
#ifdef XPAR_XISF_INTERFACE_QSPIPSU
			XQspiPsu_SelectFlash(QspiPtr,
				XQSPIPSU_SELECT_FLASH_CS_LOWER,
				XQSPIPSU_SELECT_FLASH_BUS_LOWER);
#else
			/*
			 * Set selection to L_PAGE
			 */
			XQspiPs_SetLqspiConfigReg(QspiPtr,
				LqspiCr & (~XQSPIPS_LQSPI_CR_U_PAGE_MASK));
#endif

			RealAddr = Address;
		}

#ifndef XPAR_XISF_INTERFACE_QSPIPSU
		/*
		 * Assert the Flash chip select.
		 */
		(void)XQspiPs_SetSlaveSelect(QspiPtr);
#endif
		break;
	case XISF_QSPIPS_CONNECTION_MODE_PARALLEL:
		/*
		 * The effective address in each flash is the actual
		 * address / 2
		 */
#ifdef XPAR_XISF_INTERFACE_QSPIPSU
		XQspiPsu_SelectFlash(QspiPtr,
			XQSPIPSU_SELECT_FLASH_CS_BOTH,
			XQSPIPSU_SELECT_FLASH_BUS_BOTH);
#endif
		RealAddr = Address / 2;
		break;
	default:
		/* RealAddr wont be assigned in this case */
	break;

	}
#else
		RealAddr = Address;
#endif
	return(RealAddr);
}
#endif

#ifdef XPAR_XISF_INTERFACE_OSPIPSV
/*****************************************************************************/
/**
*
* The purpose of this function is to determine the number of lines used
* for command, address and data
*
* @param	InstancePtr is a pointer to the xilisf structure.
* @param	Read is to tell whether a read or write
*
* @return	returns value to program the lines for command, address and data.
*
* @note		None.
*
*****************************************************************************/
u32 XIsf_Get_ProtoType(XIsf *InstancePtr, int Read)
{
	u32 Val;

	if(Read) {
		Val = XOSPIPSV_READ_1_8_8;
	} else {
		if (InstancePtr->SpiInstPtr->OpMode == XOSPIPSV_IDAC_MODE) {
			Val = XOSPIPSV_WRITE_1_1_1;
		} else {
			Val = XOSPIPSV_WRITE_1_1_8;
		}
	}
	return Val;
}
#endif

#ifdef XPAR_XISF_INTERFACE_PSQSPI
/*****************************************************************************/
/**
 * This functions selects the current bank
 *
 * @param	InstancePtr is a pointer to the QSPI driver component to use.
 * @param	BankSel is the bank to be selected in the flash device(s).
 *
 * @return	XST_SUCCESS if bank selected, otherwise XST_FAILURE.
 *
 * @note		None.
 *
 ******************************************************************************/
int SendBankSelect(XIsf *InstancePtr, u32 BankSel)
{
	#define EXTADD_REG_WR		0xC5U
	#define EXTADD_REG_RD		0xC8U
	#define BANK_REG_WR		0x17U
	#define BANK_SEL_SIZE		2U
	/**
	 * < BRWR or EARWR command +
	 * 1 byte bank value
	 */
	u8 WriteBuffer[5] = {0};
	u8 *NULLPtr = NULL;
	u8 WriteEnableCmdBuf = { WRITE_ENABLE_CMD };
	u32 FlashMake = InstancePtr->ManufacturerID;
	int Status = (int)(XST_FAILURE);
	/*
	 * Bank select commands for Micron and Spansion are different
	 */
	if (FlashMake == XISF_MANUFACTURER_ID_MICRON) {

		Xil_AssertNonvoid(NULLPtr == NULL);

		/*
		 * For Micron command WREN should be sent first
		 * except for some specific feature set
		 */
		Status = XIsf_Transfer(InstancePtr,
				&WriteEnableCmdBuf, NULLPtr,
					(u32)sizeof(WriteEnableCmdBuf));

		if (Status != (int)XST_SUCCESS)
			return (int)XST_FAILURE;

		WriteBuffer[BYTE1] = EXTADD_REG_WR;
		WriteBuffer[BYTE2] = (u8)BankSel;

		Xil_AssertNonvoid(NULLPtr == NULL);

		/*
		 * Send the Extended address register write command
		 * written, no receive buffer required
		 */
		Status = XIsf_Transfer(InstancePtr, WriteBuffer, NULLPtr,
				BANK_SEL_SIZE);

		if (Status != (int)XST_SUCCESS)
			return (int)XST_FAILURE;
	}
	if (FlashMake == XISF_MANUFACTURER_ID_SPANSION) {
		WriteBuffer[BYTE1] = BANK_REG_WR;
		WriteBuffer[BYTE2] = (u8)BankSel;

		Xil_AssertNonvoid(NULLPtr == NULL);

		/*
		 * Send the Extended address register write command
		 * written, no receive buffer required
		 */
		Status = XIsf_Transfer(InstancePtr, WriteBuffer, NULLPtr,
				BANK_SEL_SIZE);

		if (Status != (int)XST_SUCCESS)
			return (int)XST_FAILURE;
	}

	/* Winbond can be added here */

	return (int)(XST_SUCCESS);
}
#endif

/*****************************************************************************/
/**
 * @brief
 * This API is to set the Status Handler when an interrupt is registered
 *
 * @param	InstancePtr		Pointer to the XIsf Instance.
 * @param	XIfaceInstancePtr	Pointer to the XIsf_Iface instance to
 *					be worked on.
 * @param	XilIsf_Handler		Status handler for the application.
 *
 * @return	None
 *
 * @note		None.
 *
 ******************************************************************************/
void XIsf_SetStatusHandler(XIsf *InstancePtr, XIsf_Iface *XIfaceInstancePtr,
				XIsf_StatusHandler XilIsf_Handler)
{
	Xil_AssertVoid(InstancePtr != NULL);
	Xil_AssertVoid(XIfaceInstancePtr != NULL);
	Xil_AssertVoid(XilIsf_Handler != NULL);

	/*
	 * Setup the handler for the QSPI that will be called from the
	 * interrupt context when an QSPI status occurs, specify a pointer to
	 * the QSPI driver instance as the callback reference so the handler
	 * is able to access the instance data
	 */
#ifdef XPAR_XISF_INTERFACE_QSPIPSU
	XQspiPsu_SetStatusHandler(XIfaceInstancePtr, XIfaceInstancePtr,
			 (XQspiPsu_StatusHandler) XIsf_IfaceHandler);
#elif XPAR_XISF_INTERFACE_PSQSPI
	XQspiPs_SetStatusHandler(XIfaceInstancePtr, XIfaceInstancePtr,
			 (XQspiPs_StatusHandler) XIsf_IfaceHandler);
#elif XPAR_XISF_INTERFACE_PSSPI
	XSpiPs_SetStatusHandler(XIfaceInstancePtr, XIfaceInstancePtr,
				 (XSpiPs_StatusHandler) XIsf_IfaceHandler);
#elif XPAR_XISF_INTERFACE_AXISPI
	XSpi_SetStatusHandler(XIfaceInstancePtr, XIfaceInstancePtr,
				 (XSpi_StatusHandler) XIsf_IfaceHandler);
#elif XPAR_XISF_INTERFACE_OSPIPSV
	XOspiPsv_SetStatusHandler(XIfaceInstancePtr, XIfaceInstancePtr,
				 (XOspiPsv_StatusHandler) XIsf_IfaceHandler);
#endif

	InstancePtr->StatusHandler = XilIsf_Handler;
}


#ifndef XPAR_XISF_INTERFACE_OSPIPSV
/*****************************************************************************/
/**
 * @brief
 * This API is the handler which performs processing for the QSPI driver.
 * It is called from an interrupt context such that the amount of processing
 * performed should be minimized.  It is called when a transfer of QSPI data
 * completes or an error occurs.
 *
 * This handler provides an example of how to handle QSPI interrupts but is
 * application specific.
 *
 * @param	CallBackRef	Reference passed to the handler.
 * @param	StatusEvent	Status of the QSPI .
 * @param	ByteCount	Number of bytes transferred.
 *
 * @return	None
 *
 * @note		None.
 *
 ******************************************************************************/
void XIsf_IfaceHandler(void *CallBackRef, u32 StatusEvent,
			unsigned int ByteCount)
{

	Xil_AssertVoid(CallBackRef != NULL);

	XIsf_TransferInProgress = FALSE;

	XIsf_StatusEventInfo = StatusEvent;

	XIsf_ByteCountInfo = ByteCount;

}
#else

/*****************************************************************************/
/**
 * @brief
 * This API is the handler which performs processing for the QSPI driver.
 * It is called from an interrupt context such that the amount of processing
 * performed should be minimized.  It is called when a transfer of QSPI data
 * completes or an error occurs.
 *
 * This handler provides an example of how to handle QSPI interrupts but is
 * application specific.
 *
 * @param	CallBackRef	Reference passed to the handler.
 * @param	StatusEvent	Status of the QSPI .
 *
 * @return	None
 *
 * @note		None.
 *
 ******************************************************************************/
void XIsf_IfaceHandler(void *CallBackRef, u32 StatusEvent)
{

	Xil_AssertVoid(CallBackRef != NULL);

	XIsf_TransferInProgress = FALSE;

	XIsf_StatusEventInfo = StatusEvent;

}
#endif

